Skip to content

Commit b53366f

Browse files
Move isVariantAnalysisComplete implementation out of variant analysis manager
1 parent 7e59d4c commit b53366f

4 files changed

Lines changed: 108 additions & 107 deletions

File tree

extensions/ql-vscode/src/remote-queries/shared/variant-analysis.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,26 @@ export interface VariantAnalysisSubmission {
130130
}
131131
}
132132

133+
export async function isVariantAnalysisComplete(
134+
variantAnalysis: VariantAnalysis,
135+
artifactDownloaded: (repo: VariantAnalysisScannedRepository) => Promise<boolean>
136+
): Promise<boolean> {
137+
// It's only acceptable to have no scanned repos if the variant analysis is not in a final state.
138+
// Otherwise it means the analysis hit some kind of internal error or there were no repos to scan.
139+
if (variantAnalysis.scannedRepos === undefined || variantAnalysis.scannedRepos.length === 0) {
140+
return variantAnalysis.status !== VariantAnalysisStatus.InProgress;
141+
}
142+
143+
return (await Promise.all(variantAnalysis.scannedRepos.map(repo => isVariantAnalysisRepoComplete(repo, artifactDownloaded)))).every(x => x);
144+
}
145+
146+
async function isVariantAnalysisRepoComplete(
147+
repo: VariantAnalysisScannedRepository,
148+
artifactDownloaded: (repo: VariantAnalysisScannedRepository) => Promise<boolean>
149+
): Promise<boolean> {
150+
return hasRepoScanCompleted(repo) && (!repoHasDownloadableArtifact(repo) || await artifactDownloaded(repo));
151+
}
152+
133153
/**
134154
* @param status
135155
* @returns whether the status is in a completed state, i.e. it cannot normally change state anymore

extensions/ql-vscode/src/remote-queries/variant-analysis-manager.ts

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@ import {
1111
VariantAnalysisScannedRepository as ApiVariantAnalysisScannedRepository
1212
} from './gh-api/variant-analysis';
1313
import {
14-
hasRepoScanCompleted,
15-
repoHasDownloadableArtifact,
14+
isVariantAnalysisComplete,
1615
VariantAnalysis, VariantAnalysisQueryLanguage,
1716
VariantAnalysisScannedRepository,
1817
VariantAnalysisScannedRepositoryDownloadStatus,
1918
VariantAnalysisScannedRepositoryResult,
20-
VariantAnalysisScannedRepositoryState,
21-
VariantAnalysisStatus
19+
VariantAnalysisScannedRepositoryState
2220
} from './shared/variant-analysis';
2321
import { getErrorMessage } from '../pure/helpers-pure';
2422
import { VariantAnalysisView } from './variant-analysis-view';
@@ -68,31 +66,15 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
6866
this.variantAnalyses.set(variantAnalysis.id, variantAnalysis);
6967
await this.getView(variantAnalysis.id)?.updateView(variantAnalysis);
7068

71-
if (!await this.isVariantAnalysisComplete(variantAnalysis)) {
69+
if (!await isVariantAnalysisComplete(variantAnalysis, this.makeResultDownloadChecker(variantAnalysis))) {
7270
await commands.executeCommand('codeQL.monitorVariantAnalysis', variantAnalysis);
7371
}
7472
}
7573
}
7674

77-
public async isVariantAnalysisComplete(variantAnalysis: VariantAnalysis): Promise<boolean> {
78-
// It's only acceptable to have no scanned repos if the variant analysis is not in a final state.
79-
// Otherwise it means the analysis hit some kind of internal error or there were no repos to scan.
80-
if (variantAnalysis.scannedRepos === undefined || variantAnalysis.scannedRepos.length === 0) {
81-
return variantAnalysis.status !== VariantAnalysisStatus.InProgress;
82-
}
83-
84-
return (await Promise.all(variantAnalysis.scannedRepos.map(repo => this.isVariantAnalysisRepoComplete(variantAnalysis.id, repo)))).every(x => x);
85-
}
86-
87-
private async isVariantAnalysisRepoComplete(variantAnalysisId: number, repo: VariantAnalysisScannedRepository): Promise<boolean> {
88-
if (!hasRepoScanCompleted(repo)) {
89-
return false;
90-
} else if (!repoHasDownloadableArtifact(repo)) {
91-
return true;
92-
} else {
93-
const storageLocation = this.getVariantAnalysisStorageLocation(variantAnalysisId);
94-
return await this.variantAnalysisResultsManager.isVariantAnalysisRepoDownloaded(storageLocation, repo.repository.fullName);
95-
}
75+
private makeResultDownloadChecker(variantAnalysis: VariantAnalysis): (repo: VariantAnalysisScannedRepository) => Promise<boolean> {
76+
const storageLocation = this.getVariantAnalysisStorageLocation(variantAnalysis.id);
77+
return (repo) => this.variantAnalysisResultsManager.isVariantAnalysisRepoDownloaded(storageLocation, repo.repository.fullName);
9678
}
9779

9880
public async removeVariantAnalysis(variantAnalysis: VariantAnalysis) {

extensions/ql-vscode/src/vscode-tests/cli-integration/remote-queries/variant-analysis-manager.test.ts

Lines changed: 4 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import { CodeQLCliServer } from '../../../cli';
2222
import { storagePath } from '../global.helper';
2323
import { VariantAnalysisResultsManager } from '../../../remote-queries/variant-analysis-results-manager';
2424
import { createMockVariantAnalysis } from '../../factories/remote-queries/shared/variant-analysis';
25-
import { VariantAnalysis, VariantAnalysisStatus } from '../../../remote-queries/shared/variant-analysis';
25+
import { VariantAnalysis } from '../../../remote-queries/shared/variant-analysis';
26+
import * as VariantAnalysisModule from '../../../remote-queries/shared/variant-analysis';
2627

2728
describe('Variant Analysis Manager', async function() {
2829
let sandbox: sinon.SinonSandbox;
@@ -209,7 +210,7 @@ describe('Variant Analysis Manager', async function() {
209210

210211
describe('when the variant analysis is not complete', async () => {
211212
beforeEach(() => {
212-
sinon.stub(variantAnalysisManager, 'isVariantAnalysisComplete').resolves(false);
213+
sandbox.stub(VariantAnalysisModule, 'isVariantAnalysisComplete').resolves(false);
213214
});
214215

215216
it('should not remove the variant analysis', async () => {
@@ -225,7 +226,7 @@ describe('Variant Analysis Manager', async function() {
225226

226227
describe('when the variant analysis is complete', async () => {
227228
beforeEach(() => {
228-
sinon.stub(variantAnalysisManager, 'isVariantAnalysisComplete').resolves(true);
229+
sandbox.stub(VariantAnalysisModule, 'isVariantAnalysisComplete').resolves(true);
229230
});
230231

231232
it('should not remove the variant analysis', async () => {
@@ -240,83 +241,4 @@ describe('Variant Analysis Manager', async function() {
240241
});
241242
});
242243
});
243-
244-
describe('isVariantAnalysisComplete', async () => {
245-
let variantAnalysis: VariantAnalysis;
246-
247-
beforeEach(() => {
248-
variantAnalysis = createMockVariantAnalysis();
249-
});
250-
251-
describe('when variant analysis status is InProgress', async () => {
252-
beforeEach(() => {
253-
variantAnalysis.status = VariantAnalysisStatus.InProgress;
254-
});
255-
256-
describe('when scanned repos is undefined', async () => {
257-
it('should say the variant analysis is not complete', async () => {
258-
variantAnalysis.scannedRepos = undefined;
259-
expect(variantAnalysisManager.isVariantAnalysisComplete(variantAnalysis)).to.equal(false);
260-
});
261-
});
262-
263-
describe('when scanned repos is non-empty', async () => {
264-
describe('when not all results are downloaded', async () => {
265-
it('should say the variant analysis is not complete', async () => {
266-
sinon.stub(variantAnalysisResultsManager, 'isVariantAnalysisRepoDownloaded').resolves(false);
267-
expect(variantAnalysisManager.isVariantAnalysisComplete(variantAnalysis)).to.equal(false);
268-
});
269-
});
270-
271-
describe('when all results are downloaded', async () => {
272-
it('should say the variant analysis is complete', async () => {
273-
sinon.stub(variantAnalysisResultsManager, 'isVariantAnalysisRepoDownloaded').resolves(true);
274-
expect(variantAnalysisManager.isVariantAnalysisComplete(variantAnalysis)).to.equal(true);
275-
});
276-
});
277-
});
278-
});
279-
280-
for (const variantAnalysisStatus of [
281-
VariantAnalysisStatus.Succeeded,
282-
VariantAnalysisStatus.Failed,
283-
VariantAnalysisStatus.Canceled
284-
]) {
285-
describe(`when variant analysis status is ${variantAnalysisStatus}`, async () => {
286-
beforeEach(() => {
287-
variantAnalysis.status = variantAnalysisStatus;
288-
});
289-
290-
describe('when scanned repos is undefined', async () => {
291-
it('should say the variant analysis is complete', async () => {
292-
variantAnalysis.scannedRepos = undefined;
293-
expect(variantAnalysisManager.isVariantAnalysisComplete(variantAnalysis)).to.equal(true);
294-
});
295-
});
296-
297-
describe('when scanned repos is empty', async () => {
298-
it('should say the variant analysis is complete', async () => {
299-
variantAnalysis.scannedRepos = [];
300-
expect(variantAnalysisManager.isVariantAnalysisComplete(variantAnalysis)).to.equal(true);
301-
});
302-
});
303-
304-
describe('when scanned repos is non-empty', async () => {
305-
describe('when not all results are downloaded', async () => {
306-
it('should say the variant analysis is not complete', async () => {
307-
sinon.stub(variantAnalysisResultsManager, 'isVariantAnalysisRepoDownloaded').resolves(false);
308-
expect(variantAnalysisManager.isVariantAnalysisComplete(variantAnalysis)).to.equal(false);
309-
});
310-
});
311-
312-
describe('when all results are downloaded', async () => {
313-
it('should say the variant analysis is complete', async () => {
314-
sinon.stub(variantAnalysisResultsManager, 'isVariantAnalysisRepoDownloaded').resolves(true);
315-
expect(variantAnalysisManager.isVariantAnalysisComplete(variantAnalysis)).to.equal(true);
316-
});
317-
});
318-
});
319-
});
320-
}
321-
});
322244
});

extensions/ql-vscode/test/pure-tests/variant-analysis.test.ts

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { expect } from 'chai';
2-
import { parseVariantAnalysisQueryLanguage, VariantAnalysisQueryLanguage } from '../../src/remote-queries/shared/variant-analysis';
2+
import { VariantAnalysis, parseVariantAnalysisQueryLanguage, VariantAnalysisQueryLanguage, VariantAnalysisStatus, isVariantAnalysisComplete } from '../../src/remote-queries/shared/variant-analysis';
3+
import { createMockVariantAnalysis } from '../../src/vscode-tests/factories/remote-queries/shared/variant-analysis';
34

45
describe('parseVariantAnalysisQueryLanguage', () => {
56
it('parses a valid language', () => {
@@ -10,3 +11,79 @@ describe('parseVariantAnalysisQueryLanguage', () => {
1011
expect(parseVariantAnalysisQueryLanguage('rubbish')).to.not.exist;
1112
});
1213
});
14+
15+
describe('isVariantAnalysisComplete', async () => {
16+
let variantAnalysis: VariantAnalysis;
17+
const uncallableArtifactDownloadChecker = () => { throw new Error('Should not be called'); };
18+
19+
beforeEach(() => {
20+
variantAnalysis = createMockVariantAnalysis();
21+
});
22+
23+
describe('when variant analysis status is InProgress', async () => {
24+
beforeEach(() => {
25+
variantAnalysis.status = VariantAnalysisStatus.InProgress;
26+
});
27+
28+
describe('when scanned repos is undefined', async () => {
29+
it('should say the variant analysis is not complete', async () => {
30+
variantAnalysis.scannedRepos = undefined;
31+
expect(isVariantAnalysisComplete(variantAnalysis, uncallableArtifactDownloadChecker)).to.equal(false);
32+
});
33+
});
34+
35+
describe('when scanned repos is non-empty', async () => {
36+
describe('when not all results are downloaded', async () => {
37+
it('should say the variant analysis is not complete', async () => {
38+
expect(isVariantAnalysisComplete(variantAnalysis, async () => false)).to.equal(false);
39+
});
40+
});
41+
42+
describe('when all results are downloaded', async () => {
43+
it('should say the variant analysis is complete', async () => {
44+
expect(isVariantAnalysisComplete(variantAnalysis, async () => true)).to.equal(true);
45+
});
46+
});
47+
});
48+
});
49+
50+
for (const variantAnalysisStatus of [
51+
VariantAnalysisStatus.Succeeded,
52+
VariantAnalysisStatus.Failed,
53+
VariantAnalysisStatus.Canceled
54+
]) {
55+
describe(`when variant analysis status is ${variantAnalysisStatus}`, async () => {
56+
beforeEach(() => {
57+
variantAnalysis.status = variantAnalysisStatus;
58+
});
59+
60+
describe('when scanned repos is undefined', async () => {
61+
it('should say the variant analysis is complete', async () => {
62+
variantAnalysis.scannedRepos = undefined;
63+
expect(isVariantAnalysisComplete(variantAnalysis, uncallableArtifactDownloadChecker)).to.equal(true);
64+
});
65+
});
66+
67+
describe('when scanned repos is empty', async () => {
68+
it('should say the variant analysis is complete', async () => {
69+
variantAnalysis.scannedRepos = [];
70+
expect(isVariantAnalysisComplete(variantAnalysis, uncallableArtifactDownloadChecker)).to.equal(true);
71+
});
72+
});
73+
74+
describe('when scanned repos is non-empty', async () => {
75+
describe('when not all results are downloaded', async () => {
76+
it('should say the variant analysis is not complete', async () => {
77+
expect(isVariantAnalysisComplete(variantAnalysis, async () => false)).to.equal(false);
78+
});
79+
});
80+
81+
describe('when all results are downloaded', async () => {
82+
it('should say the variant analysis is complete', async () => {
83+
expect(isVariantAnalysisComplete(variantAnalysis, async () => true)).to.equal(true);
84+
});
85+
});
86+
});
87+
});
88+
}
89+
});

0 commit comments

Comments
 (0)