Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/test/inline/review.stest.ts
13388 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import assert from 'assert';
7
import path from 'path';
8
import { FeedbackGenerator } from '../../src/extension/prompt/node/feedbackGenerator';
9
import { CHAT_MODEL } from '../../src/platform/configuration/common/configurationService';
10
import { TextDocumentSnapshot } from '../../src/platform/editing/common/textDocumentSnapshot';
11
import { ReviewComment } from '../../src/platform/review/common/reviewService';
12
import { TestingServiceCollection } from '../../src/platform/test/node/services';
13
import { IInstantiationService } from '../../src/util/vs/platform/instantiation/common/instantiation';
14
import { CancellationTokenSource, Range } from '../../src/vscodeTypes';
15
import { ssuite, stest } from '../base/stest';
16
import { setupSimulationWorkspace, teardownSimulationWorkspace } from '../simulation/inlineChatSimulator';
17
import { forEachModel, fromFixture } from '../simulation/stestUtil';
18
19
const models = [CHAT_MODEL.GPT41];
20
21
ssuite({ title: '/review', location: 'inline' }, forEachModel(models, model => {
22
23
stest({ description: 'Binary search with incorrect stop condition', language: 'javascript', model }, async (testingServiceCollection) => {
24
const comments = await generateComments(testingServiceCollection, 'review/binary-search-1.js');
25
const expectedLine = 4;
26
const expectedContent = 'left <= right';
27
const expectedMinRelevance = 10;
28
const expectedKind = 'bug';
29
assertComment(comments, expectedLine, expectedContent, expectedMinRelevance, expectedKind);
30
});
31
32
stest({ description: 'Binary search with correct stop condition', language: 'javascript', model }, async (testingServiceCollection) => {
33
const comments = await generateComments(testingServiceCollection, 'review/binary-search-2.js');
34
assertNoHighPriorityCommentOrBug(comments);
35
});
36
37
stest({ description: 'Bank account with missing lock acquisition', language: 'python', model }, async (testingServiceCollection) => {
38
const comments = await generateComments(testingServiceCollection, 'review/bank-account-1.py');
39
const expectedLines = [15, 16, 18, 19];
40
const expectedContent = 'lock';
41
const expectedMinRelevance = 5;
42
const expectedKinds = ['bug', 'consistency'];
43
assertComment(comments, expectedLines, expectedContent, expectedMinRelevance, expectedKinds);
44
});
45
46
stest({ description: 'Bank account with lock acquisition', language: 'python', model }, async (testingServiceCollection) => {
47
const comments = await generateComments(testingServiceCollection, 'review/bank-account-2.py');
48
const unexpected = comments.filter(c => ['bug', 'consistency'].includes(c.kind) && (typeof c.body === 'string' ? c.body : c.body.value).indexOf('lock') !== -1);
49
assert.strictEqual(unexpected.length, 0);
50
});
51
52
stest({ description: 'InstantiationService this scoping bug', language: 'typescript', model }, async (testingServiceCollection) => {
53
const comments = await generateComments(testingServiceCollection, 'review/nested-services-1.ts');
54
const expectedLine = 9;
55
const expectedContent = 'this._parent._children.delete';
56
const expectedMinRelevance = 5;
57
const expectedKind = 'bug';
58
assertComment(comments, expectedLine, expectedContent, expectedMinRelevance, expectedKind);
59
});
60
61
stest({ description: 'InstantiationService this scoping fixed', language: 'typescript', model }, async (testingServiceCollection) => {
62
const comments = await generateComments(testingServiceCollection, 'review/nested-services-2.ts');
63
const unexpected = comments.filter(c => c.kind === 'bug' && c.range.start.line === 10);
64
assert.strictEqual(unexpected.length, 0);
65
});
66
}));
67
68
async function generateComments(testingServiceCollection: TestingServiceCollection, relativeFixturePath: string) {
69
const workspace = setupSimulationWorkspace(testingServiceCollection, { files: [fromFixture(relativeFixturePath)] });
70
const accessor = testingServiceCollection.createTestingAccessor();
71
const instantiationService = accessor.get(IInstantiationService);
72
73
const source = new CancellationTokenSource();
74
try {
75
const relativeDocumentPath = path.basename(relativeFixturePath);
76
const document = TextDocumentSnapshot.create(workspace.getDocument(relativeDocumentPath).document);
77
const feedbackGenerator = instantiationService.createInstance(FeedbackGenerator);
78
const result = await feedbackGenerator.generateComments([
79
{
80
document,
81
relativeDocumentPath,
82
selection: new Range(0, 0, document.lineCount, 0),
83
}
84
], source.token);
85
return result.type === 'success' ? result.comments : [];
86
} finally {
87
source.dispose();
88
await teardownSimulationWorkspace(accessor, workspace);
89
}
90
}
91
92
function assertComment(comments: ReviewComment[], expectedLines: number | number[], expectedContent: string, expectedMinRelevance: number, expectedKind: string | string[]) {
93
const lines = Array.isArray(expectedLines) ? expectedLines : [expectedLines];
94
const lineComment = comments?.find(d => lines.indexOf(d.range.start.line) !== -1);
95
assert.ok(lineComment, `Expected comment for line(s) ${lines.join(', ')}.`);
96
const message = typeof lineComment.body === 'string' ? lineComment.body : lineComment.body.value;
97
assert.ok(message.includes(expectedContent), `Expected comment for line(s) ${lines.join(', ')} to contain "${expectedContent}"`);
98
// assert.ok(typeof lineComment.relevance === 'number' && lineComment.relevance >= expectedMinRelevance, `Expected comment to have relevance >= ${expectedMinRelevance}, was: ${lineComment.relevance}`);
99
const kinds = Array.isArray(expectedKind) ? expectedKind : [expectedKind];
100
assert.ok(kinds.indexOf(lineComment.kind) !== -1, `Expected ${kinds.join(', ')} comment, was: ${lineComment.kind}`);
101
}
102
103
function assertNoHighPriorityCommentOrBug(comments: ReviewComment[]) {
104
// const highPriority = comments.filter(d => d.relevance === 10);
105
// assert.strictEqual(highPriority.length, 0, `Expected no high priority comment`);
106
const bugs = comments.filter(d => d.kind === 'bug');
107
assert.strictEqual(bugs.length, 0, `Expected no bug comment`);
108
}
109
110
export function logComments(comments: ReviewComment[]) {
111
console.log(JSON.stringify(comments.map(c => ({
112
line: c.range.start.line,
113
content: typeof c.body === 'string' ? c.body : c.body.value,
114
severity: c.severity,
115
kind: c.kind
116
})), null, 2));
117
}
118
119