Skip to content

Commit

Permalink
Add test that asserts stream is done when the request is done (micros…
Browse files Browse the repository at this point in the history
…oft#202184)

test that asserts stream is done when the request is done

manifests fixing microsoft/vscode-copilot#3345
  • Loading branch information
jrieken authored Jan 10, 2024
1 parent 53d7995 commit 115155d
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { WindowIntervalTimer } from 'vs/base/browser/dom';
import { coalesceInPlace, equals, tail } from 'vs/base/common/arrays';
import { AsyncIterableObject, AsyncIterableSource, IntervalTimer } from 'vs/base/common/async';
import { AsyncIterableSource, IntervalTimer } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Emitter, Event } from 'vs/base/common/event';
import { Iterable } from 'vs/base/common/iterator';
Expand Down Expand Up @@ -439,21 +439,12 @@ export async function performAsyncTextEdit(model: ITextModel, edit: AsyncTextEdi
}
}

export function asAsyncEdit(edit: IIdentifiedSingleEditOperation): AsyncTextEdit {
return {
range: edit.range,
newText: AsyncIterableObject.fromArray([edit.text ?? ''])
} satisfies AsyncTextEdit;
}

export function asProgressiveEdit(interval: IntervalTimer, edit: IIdentifiedSingleEditOperation, wordsPerSec: number, token: CancellationToken): AsyncTextEdit {

wordsPerSec = Math.max(10, wordsPerSec);

const stream = new AsyncIterableSource<string>();
let newText = edit.text ?? '';
// const wordCount = countWords(newText);


interval.cancelAndSet(() => {
const r = getNWords(newText, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

import * as assert from 'assert';
import { equals } from 'vs/base/common/arrays';
import { timeout } from 'vs/base/common/async';
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { mock } from 'vs/base/test/common/mock';
import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { TestDiffProviderFactoryService } from 'vs/editor/browser/diff/testDiffProviderFactoryService';
import { IActiveCodeEditor } from 'vs/editor/browser/editorBrowser';
Expand All @@ -31,7 +33,7 @@ import { IChatAccessibilityService } from 'vs/workbench/contrib/chat/browser/cha
import { IChatResponseViewModel } from 'vs/workbench/contrib/chat/common/chatViewModel';
import { InlineChatController, InlineChatRunOptions, State } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController';
import { IInlineChatSessionService, InlineChatSessionService } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession';
import { IInlineChatService, InlineChatConfigKeys, InlineChatResponseType } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
import { EditMode, IInlineChatService, InlineChatConfigKeys, InlineChatResponseType } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
import { InlineChatServiceImpl } from 'vs/workbench/contrib/inlineChat/common/inlineChatServiceImpl';
import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';

Expand Down Expand Up @@ -371,4 +373,56 @@ suite('InteractiveChatController', function () {
editor.getModel().undo();
assert.strictEqual(editor.getModel().getValue(), valueThen);
});

test('UI is streaming edits minutes after the response is finished #3345', async function () {

configurationService.setUserConfiguration(InlineChatConfigKeys.Mode, EditMode.Live);

return runWithFakedTimers({ maxTaskCount: Number.MAX_SAFE_INTEGER }, async () => {

const d = inlineChatService.addProvider({
debugName: 'Unit Test',
label: 'Unit Test',
prepareInlineChatSession() {
return {
id: Math.random(),
};
},
async provideResponse(session, request, progress) {

const text = '${CSI}#a\n${CSI}#b\n${CSI}#c\n';

await timeout(10);
progress.report({ edits: [{ range: new Range(1, 1, 1, 1), text: text }] });

await timeout(10);
progress.report({ edits: [{ range: new Range(1, 1, 1, 1), text: text.repeat(1000) + 'DONE' }] });

throw new Error('Too long');
}
});


let modelChangeCounter = 0;
store.add(editor.getModel().onDidChangeContent(() => { modelChangeCounter++; }));

store.add(d);
ctrl = instaService.createInstance(TestController, editor);
const p = ctrl.waitFor([...TestController.INIT_SEQUENCE, State.MAKE_REQUEST, State.APPLY_RESPONSE, State.SHOW_RESPONSE, State.WAIT_FOR_INPUT]);
const r = ctrl.run({ message: 'Hello', autoSend: true });
await p;

assert.ok(modelChangeCounter > 0); // some changes have been made

const modelChangeCounterNow = modelChangeCounter;

await timeout(10);

assert.strictEqual(modelChangeCounterNow, modelChangeCounter);
assert.ok(!editor.getModel().getValue().includes('DONE'));

await ctrl.cancelSession();
await r;
});
});
});

0 comments on commit 115155d

Please sign in to comment.