Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/notebook/test/browser/notebookKernelService.test.ts
3296 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 { URI } from '../../../../../base/common/uri.js';
8
import { ExtensionIdentifier } from '../../../../../platform/extensions/common/extensions.js';
9
import { setupInstantiationService } from './testNotebookEditor.js';
10
import { Emitter, Event } from '../../../../../base/common/event.js';
11
import { INotebookKernel, INotebookKernelService, VariablesResult } from '../../common/notebookKernelService.js';
12
import { NotebookKernelService } from '../../browser/services/notebookKernelServiceImpl.js';
13
import { INotebookService } from '../../common/notebookService.js';
14
import { mock } from '../../../../../base/test/common/mock.js';
15
import { TestInstantiationService } from '../../../../../platform/instantiation/test/common/instantiationServiceMock.js';
16
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
17
import { NotebookTextModel } from '../../common/model/notebookTextModel.js';
18
import { PLAINTEXT_LANGUAGE_ID } from '../../../../../editor/common/languages/modesRegistry.js';
19
import { IMenu, IMenuService } from '../../../../../platform/actions/common/actions.js';
20
import { TransientOptions } from '../../common/notebookCommon.js';
21
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
22
import { CancellationToken } from '../../../../../base/common/cancellation.js';
23
import { AsyncIterableObject } from '../../../../../base/common/async.js';
24
25
suite('NotebookKernelService', () => {
26
27
let instantiationService: TestInstantiationService;
28
let kernelService: INotebookKernelService;
29
let disposables: DisposableStore;
30
31
let onDidAddNotebookDocument: Emitter<NotebookTextModel>;
32
teardown(() => {
33
disposables.dispose();
34
});
35
36
ensureNoDisposablesAreLeakedInTestSuite();
37
38
setup(function () {
39
disposables = new DisposableStore();
40
41
onDidAddNotebookDocument = new Emitter();
42
disposables.add(onDidAddNotebookDocument);
43
44
instantiationService = setupInstantiationService(disposables);
45
instantiationService.stub(INotebookService, new class extends mock<INotebookService>() {
46
override onDidAddNotebookDocument = onDidAddNotebookDocument.event;
47
override onWillRemoveNotebookDocument = Event.None;
48
override getNotebookTextModels() { return []; }
49
});
50
instantiationService.stub(IMenuService, new class extends mock<IMenuService>() {
51
override createMenu() {
52
return new class extends mock<IMenu>() {
53
override onDidChange = Event.None;
54
override getActions() { return []; }
55
override dispose() { }
56
};
57
}
58
});
59
kernelService = disposables.add(instantiationService.createInstance(NotebookKernelService));
60
instantiationService.set(INotebookKernelService, kernelService);
61
});
62
63
test('notebook priorities', function () {
64
65
const u1 = URI.parse('foo:///one');
66
const u2 = URI.parse('foo:///two');
67
68
const k1 = new TestNotebookKernel({ label: 'z' });
69
const k2 = new TestNotebookKernel({ label: 'a' });
70
71
disposables.add(kernelService.registerKernel(k1));
72
disposables.add(kernelService.registerKernel(k2));
73
74
// equal priorities -> sort by name
75
let info = kernelService.getMatchingKernel({ uri: u1, notebookType: 'foo' });
76
assert.ok(info.all[0] === k2);
77
assert.ok(info.all[1] === k1);
78
79
// update priorities for u1 notebook
80
kernelService.updateKernelNotebookAffinity(k2, u1, 2);
81
kernelService.updateKernelNotebookAffinity(k2, u2, 1);
82
83
// updated
84
info = kernelService.getMatchingKernel({ uri: u1, notebookType: 'foo' });
85
assert.ok(info.all[0] === k2);
86
assert.ok(info.all[1] === k1);
87
88
// NOT updated
89
info = kernelService.getMatchingKernel({ uri: u2, notebookType: 'foo' });
90
assert.ok(info.all[0] === k2);
91
assert.ok(info.all[1] === k1);
92
93
// reset
94
kernelService.updateKernelNotebookAffinity(k2, u1, undefined);
95
info = kernelService.getMatchingKernel({ uri: u1, notebookType: 'foo' });
96
assert.ok(info.all[0] === k2);
97
assert.ok(info.all[1] === k1);
98
});
99
100
test('new kernel with higher affinity wins, https://github.com/microsoft/vscode/issues/122028', function () {
101
const notebook = URI.parse('foo:///one');
102
103
const kernel = new TestNotebookKernel();
104
disposables.add(kernelService.registerKernel(kernel));
105
106
let info = kernelService.getMatchingKernel({ uri: notebook, notebookType: 'foo' });
107
assert.strictEqual(info.all.length, 1);
108
assert.ok(info.all[0] === kernel);
109
110
const betterKernel = new TestNotebookKernel();
111
disposables.add(kernelService.registerKernel(betterKernel));
112
113
info = kernelService.getMatchingKernel({ uri: notebook, notebookType: 'foo' });
114
assert.strictEqual(info.all.length, 2);
115
116
kernelService.updateKernelNotebookAffinity(betterKernel, notebook, 2);
117
info = kernelService.getMatchingKernel({ uri: notebook, notebookType: 'foo' });
118
assert.strictEqual(info.all.length, 2);
119
assert.ok(info.all[0] === betterKernel);
120
assert.ok(info.all[1] === kernel);
121
});
122
123
test('onDidChangeSelectedNotebooks not fired on initial notebook open #121904', function () {
124
125
const uri = URI.parse('foo:///one');
126
const jupyter = { uri, viewType: 'jupyter', notebookType: 'jupyter' };
127
const dotnet = { uri, viewType: 'dotnet', notebookType: 'dotnet' };
128
129
const jupyterKernel = new TestNotebookKernel({ viewType: jupyter.viewType });
130
const dotnetKernel = new TestNotebookKernel({ viewType: dotnet.viewType });
131
disposables.add(kernelService.registerKernel(jupyterKernel));
132
disposables.add(kernelService.registerKernel(dotnetKernel));
133
134
kernelService.selectKernelForNotebook(jupyterKernel, jupyter);
135
kernelService.selectKernelForNotebook(dotnetKernel, dotnet);
136
137
let info = kernelService.getMatchingKernel(dotnet);
138
assert.strictEqual(info.selected === dotnetKernel, true);
139
140
info = kernelService.getMatchingKernel(jupyter);
141
assert.strictEqual(info.selected === jupyterKernel, true);
142
});
143
144
test('onDidChangeSelectedNotebooks not fired on initial notebook open #121904, p2', async function () {
145
146
const uri = URI.parse('foo:///one');
147
const jupyter = { uri, viewType: 'jupyter', notebookType: 'jupyter' };
148
const dotnet = { uri, viewType: 'dotnet', notebookType: 'dotnet' };
149
150
const jupyterKernel = new TestNotebookKernel({ viewType: jupyter.viewType });
151
const dotnetKernel = new TestNotebookKernel({ viewType: dotnet.viewType });
152
disposables.add(kernelService.registerKernel(jupyterKernel));
153
disposables.add(kernelService.registerKernel(dotnetKernel));
154
155
kernelService.selectKernelForNotebook(jupyterKernel, jupyter);
156
kernelService.selectKernelForNotebook(dotnetKernel, dotnet);
157
158
const transientOptions: TransientOptions = {
159
transientOutputs: false,
160
transientCellMetadata: {},
161
transientDocumentMetadata: {},
162
cellContentMetadata: {},
163
};
164
165
{
166
// open as jupyter -> bind event
167
const p1 = Event.toPromise(kernelService.onDidChangeSelectedNotebooks);
168
const d1 = disposables.add(instantiationService.createInstance(NotebookTextModel, jupyter.viewType, jupyter.uri, [], {}, transientOptions));
169
onDidAddNotebookDocument.fire(d1);
170
const event = await p1;
171
assert.strictEqual(event.newKernel, jupyterKernel.id);
172
}
173
{
174
// RE-open as dotnet -> bind event
175
const p2 = Event.toPromise(kernelService.onDidChangeSelectedNotebooks);
176
const d2 = disposables.add(instantiationService.createInstance(NotebookTextModel, dotnet.viewType, dotnet.uri, [], {}, transientOptions));
177
onDidAddNotebookDocument.fire(d2);
178
const event2 = await p2;
179
assert.strictEqual(event2.newKernel, dotnetKernel.id);
180
}
181
});
182
});
183
184
class TestNotebookKernel implements INotebookKernel {
185
id: string = Math.random() + 'kernel';
186
label: string = 'test-label';
187
viewType = '*';
188
onDidChange = Event.None;
189
extension: ExtensionIdentifier = new ExtensionIdentifier('test');
190
localResourceRoot: URI = URI.file('/test');
191
description?: string | undefined;
192
detail?: string | undefined;
193
preloadUris: URI[] = [];
194
preloadProvides: string[] = [];
195
supportedLanguages: string[] = [];
196
executeNotebookCellsRequest(): Promise<void> {
197
throw new Error('Method not implemented.');
198
}
199
cancelNotebookCellExecution(): Promise<void> {
200
throw new Error('Method not implemented.');
201
}
202
provideVariables(notebookUri: URI, parentId: number | undefined, kind: 'named' | 'indexed', start: number, token: CancellationToken): AsyncIterableObject<VariablesResult> {
203
return AsyncIterableObject.EMPTY;
204
}
205
206
constructor(opts?: { languages?: string[]; label?: string; viewType?: string }) {
207
this.supportedLanguages = opts?.languages ?? [PLAINTEXT_LANGUAGE_ID];
208
this.label = opts?.label ?? this.label;
209
this.viewType = opts?.viewType ?? this.viewType;
210
}
211
}
212
213