Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/extensionManagement/test/common/extensionsProfileScannerService.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 * as sinon from 'sinon';
8
import { VSBuffer } from '../../../../base/common/buffer.js';
9
import { joinPath } from '../../../../base/common/resources.js';
10
import { URI } from '../../../../base/common/uri.js';
11
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';
12
import { IEnvironmentService } from '../../../environment/common/environment.js';
13
import { AbstractExtensionsProfileScannerService, ProfileExtensionsEvent } from '../../common/extensionsProfileScannerService.js';
14
import { ExtensionType, IExtension, IExtensionManifest, TargetPlatform } from '../../../extensions/common/extensions.js';
15
import { FileService } from '../../../files/common/fileService.js';
16
import { IFileService } from '../../../files/common/files.js';
17
import { InMemoryFileSystemProvider } from '../../../files/common/inMemoryFilesystemProvider.js';
18
import { TestInstantiationService } from '../../../instantiation/test/common/instantiationServiceMock.js';
19
import { ILogService, NullLogService } from '../../../log/common/log.js';
20
import { ITelemetryService } from '../../../telemetry/common/telemetry.js';
21
import { NullTelemetryService } from '../../../telemetry/common/telemetryUtils.js';
22
import { IUriIdentityService } from '../../../uriIdentity/common/uriIdentity.js';
23
import { UriIdentityService } from '../../../uriIdentity/common/uriIdentityService.js';
24
import { IUserDataProfilesService, UserDataProfilesService } from '../../../userDataProfile/common/userDataProfile.js';
25
26
class TestObject extends AbstractExtensionsProfileScannerService { }
27
28
suite('ExtensionsProfileScannerService', () => {
29
30
const ROOT = URI.file('/ROOT');
31
const disposables = ensureNoDisposablesAreLeakedInTestSuite();
32
33
const extensionsLocation = joinPath(ROOT, 'extensions');
34
let instantiationService: TestInstantiationService;
35
36
setup(async () => {
37
instantiationService = disposables.add(new TestInstantiationService());
38
const logService = new NullLogService();
39
const fileService = disposables.add(new FileService(logService));
40
const fileSystemProvider = disposables.add(new InMemoryFileSystemProvider());
41
disposables.add(fileService.registerProvider(ROOT.scheme, fileSystemProvider));
42
instantiationService.stub(ILogService, logService);
43
instantiationService.stub(IFileService, fileService);
44
instantiationService.stub(ITelemetryService, NullTelemetryService);
45
const uriIdentityService = instantiationService.stub(IUriIdentityService, disposables.add(new UriIdentityService(fileService)));
46
const environmentService = instantiationService.stub(IEnvironmentService, { userRoamingDataHome: ROOT, cacheHome: joinPath(ROOT, 'cache'), });
47
const userDataProfilesService = disposables.add(new UserDataProfilesService(environmentService, fileService, uriIdentityService, logService));
48
instantiationService.stub(IUserDataProfilesService, userDataProfilesService);
49
});
50
51
suiteTeardown(() => sinon.restore());
52
53
test('write extensions located in the same extensions folder', async () => {
54
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
55
56
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
57
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
58
await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest);
59
60
const actual = await testObject.scanProfileExtensions(extensionsManifest);
61
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]);
62
});
63
64
test('write extensions located in the different folder', async () => {
65
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
66
67
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
68
const extension = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0'));
69
await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest);
70
71
const actual = await testObject.scanProfileExtensions(extensionsManifest);
72
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]);
73
});
74
75
test('write extensions located in the same extensions folder has relative location ', async () => {
76
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
77
78
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
79
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
80
await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest);
81
82
const actual = JSON.parse((await instantiationService.get(IFileService).readFile(extensionsManifest)).value.toString());
83
assert.deepStrictEqual(actual, [{ identifier: extension.identifier, location: extension.location.toJSON(), relativeLocation: 'pub.a-1.0.0', version: extension.manifest.version }]);
84
});
85
86
test('write extensions located in different extensions folder does not has relative location ', async () => {
87
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
88
89
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
90
const extension = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0'));
91
await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest);
92
93
const actual = JSON.parse((await instantiationService.get(IFileService).readFile(extensionsManifest)).value.toString());
94
assert.deepStrictEqual(actual, [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version }]);
95
});
96
97
test('extension in old format is read and migrated', async () => {
98
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
99
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
100
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
101
identifier: extension.identifier,
102
location: extension.location.toJSON(),
103
version: extension.manifest.version,
104
}])));
105
106
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
107
108
const actual = await testObject.scanProfileExtensions(extensionsManifest);
109
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]);
110
111
const manifestContent = JSON.parse((await instantiationService.get(IFileService).readFile(extensionsManifest)).value.toString());
112
assert.deepStrictEqual(manifestContent, [{ identifier: extension.identifier, location: extension.location.toJSON(), relativeLocation: 'pub.a-1.0.0', version: extension.manifest.version }]);
113
});
114
115
test('extension in old format is not migrated if not exists in same location', async () => {
116
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
117
const extension = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0'));
118
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
119
identifier: extension.identifier,
120
location: extension.location.toJSON(),
121
version: extension.manifest.version,
122
}])));
123
124
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
125
126
const actual = await testObject.scanProfileExtensions(extensionsManifest);
127
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]);
128
129
const manifestContent = JSON.parse((await instantiationService.get(IFileService).readFile(extensionsManifest)).value.toString());
130
assert.deepStrictEqual(manifestContent, [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version }]);
131
});
132
133
test('extension in old format is read and migrated during write', async () => {
134
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
135
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
136
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
137
identifier: extension.identifier,
138
location: extension.location.toJSON(),
139
version: extension.manifest.version,
140
}])));
141
142
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
143
const extension2 = aExtension('pub.b', joinPath(extensionsLocation, 'pub.b-1.0.0'));
144
await testObject.addExtensionsToProfile([[extension2, undefined]], extensionsManifest);
145
146
const actual = await testObject.scanProfileExtensions(extensionsManifest);
147
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [
148
{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined },
149
{ identifier: extension2.identifier, location: extension2.location.toJSON(), version: extension2.manifest.version, metadata: undefined }
150
]);
151
152
const manifestContent = JSON.parse((await instantiationService.get(IFileService).readFile(extensionsManifest)).value.toString());
153
assert.deepStrictEqual(manifestContent, [
154
{ identifier: extension.identifier, location: extension.location.toJSON(), relativeLocation: 'pub.a-1.0.0', version: extension.manifest.version },
155
{ identifier: extension2.identifier, location: extension2.location.toJSON(), relativeLocation: 'pub.b-1.0.0', version: extension2.manifest.version }
156
]);
157
});
158
159
test('extensions in old format and new format is read and migrated', async () => {
160
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
161
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
162
const extension2 = aExtension('pub.b', joinPath(extensionsLocation, 'pub.b-1.0.0'));
163
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
164
identifier: extension.identifier,
165
location: extension.location.toJSON(),
166
version: extension.manifest.version,
167
}, {
168
identifier: extension2.identifier,
169
location: extension2.location.toJSON(),
170
relativeLocation: 'pub.b-1.0.0',
171
version: extension2.manifest.version,
172
}])));
173
174
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
175
176
const actual = await testObject.scanProfileExtensions(extensionsManifest);
177
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [
178
{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined },
179
{ identifier: extension2.identifier, location: extension2.location.toJSON(), version: extension2.manifest.version, metadata: undefined }
180
]);
181
182
const manifestContent = JSON.parse((await instantiationService.get(IFileService).readFile(extensionsManifest)).value.toString());
183
assert.deepStrictEqual(manifestContent, [
184
{ identifier: extension.identifier, location: extension.location.toJSON(), relativeLocation: 'pub.a-1.0.0', version: extension.manifest.version },
185
{ identifier: extension2.identifier, location: extension2.location.toJSON(), relativeLocation: 'pub.b-1.0.0', version: extension2.manifest.version }
186
]);
187
});
188
189
test('throws error if extension has invalid relativePath', async () => {
190
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
191
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
192
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
193
identifier: extension.identifier,
194
location: extension.location.toJSON(),
195
version: extension.manifest.version,
196
relativePath: 2
197
}])));
198
199
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
200
201
try {
202
await testObject.scanProfileExtensions(extensionsManifest);
203
assert.fail('Should throw error');
204
} catch (error) { /*expected*/ }
205
});
206
207
test('throws error if extension has no location', async () => {
208
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
209
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
210
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
211
identifier: extension.identifier,
212
version: extension.manifest.version,
213
relativePath: 'pub.a-1.0.0'
214
}])));
215
216
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
217
218
try {
219
await testObject.scanProfileExtensions(extensionsManifest);
220
assert.fail('Should throw error');
221
} catch (error) { /*expected*/ }
222
});
223
224
test('throws error if extension location is invalid', async () => {
225
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
226
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
227
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
228
identifier: extension.identifier,
229
location: {},
230
version: extension.manifest.version,
231
relativePath: 'pub.a-1.0.0'
232
}])));
233
234
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
235
236
try {
237
await testObject.scanProfileExtensions(extensionsManifest);
238
assert.fail('Should throw error');
239
} catch (error) { /*expected*/ }
240
});
241
242
test('throws error if extension has no identifier', async () => {
243
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
244
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
245
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
246
location: extension.location.toJSON(),
247
version: extension.manifest.version,
248
}])));
249
250
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
251
252
try {
253
await testObject.scanProfileExtensions(extensionsManifest);
254
assert.fail('Should throw error');
255
} catch (error) { /*expected*/ }
256
});
257
258
test('throws error if extension identifier is invalid', async () => {
259
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
260
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
261
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
262
identifier: 'pub.a',
263
location: extension.location.toJSON(),
264
version: extension.manifest.version,
265
}])));
266
267
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
268
269
try {
270
await testObject.scanProfileExtensions(extensionsManifest);
271
assert.fail('Should throw error');
272
} catch (error) { /*expected*/ }
273
});
274
275
test('throws error if extension has no version', async () => {
276
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
277
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
278
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
279
identifier: extension.identifier,
280
location: extension.location.toJSON(),
281
}])));
282
283
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
284
285
try {
286
await testObject.scanProfileExtensions(extensionsManifest);
287
assert.fail('Should throw error');
288
} catch (error) { /*expected*/ }
289
});
290
291
test('read extension when manifest is empty', async () => {
292
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
293
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(''));
294
295
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
296
const actual = await testObject.scanProfileExtensions(extensionsManifest);
297
assert.deepStrictEqual(actual, []);
298
});
299
300
test('read extension when manifest has empty lines and spaces', async () => {
301
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
302
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(`
303
304
305
`));
306
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
307
const actual = await testObject.scanProfileExtensions(extensionsManifest);
308
assert.deepStrictEqual(actual, []);
309
});
310
311
test('read extension when the relative location is empty', async () => {
312
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
313
const extension = aExtension('pub.a', joinPath(extensionsLocation, 'pub.a-1.0.0'));
314
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
315
identifier: extension.identifier,
316
location: extension.location.toJSON(),
317
relativeLocation: '',
318
version: extension.manifest.version,
319
}])));
320
321
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
322
323
const actual = await testObject.scanProfileExtensions(extensionsManifest);
324
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]);
325
326
const manifestContent = JSON.parse((await instantiationService.get(IFileService).readFile(extensionsManifest)).value.toString());
327
assert.deepStrictEqual(manifestContent, [{ identifier: extension.identifier, location: extension.location.toJSON(), relativeLocation: 'pub.a-1.0.0', version: extension.manifest.version }]);
328
});
329
330
test('add extension trigger events', async () => {
331
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
332
const target1 = sinon.stub();
333
const target2 = sinon.stub();
334
disposables.add(testObject.onAddExtensions(target1));
335
disposables.add(testObject.onDidAddExtensions(target2));
336
337
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
338
const extension = aExtension('pub.a', joinPath(ROOT, 'foo', 'pub.a-1.0.0'));
339
await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest);
340
341
const actual = await testObject.scanProfileExtensions(extensionsManifest);
342
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]);
343
344
assert.ok(target1.calledOnce);
345
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
346
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions.length, 1);
347
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].identifier, extension.identifier);
348
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].version, extension.manifest.version);
349
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].location.toString(), extension.location.toString());
350
351
assert.ok(target2.calledOnce);
352
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
353
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions.length, 1);
354
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].identifier, extension.identifier);
355
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].version, extension.manifest.version);
356
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].location.toString(), extension.location.toString());
357
});
358
359
test('remove extensions trigger events', async () => {
360
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
361
const target1 = sinon.stub();
362
const target2 = sinon.stub();
363
disposables.add(testObject.onRemoveExtensions(target1));
364
disposables.add(testObject.onDidRemoveExtensions(target2));
365
366
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
367
const extension1 = aExtension('pub.a', joinPath(ROOT, 'foo', 'pub.a-1.0.0'));
368
const extension2 = aExtension('pub.b', joinPath(ROOT, 'foo', 'pub.b-1.0.0'));
369
await testObject.addExtensionsToProfile([[extension1, undefined], [extension2, undefined]], extensionsManifest);
370
await testObject.removeExtensionsFromProfile([extension1.identifier, extension2.identifier], extensionsManifest);
371
372
const actual = await testObject.scanProfileExtensions(extensionsManifest);
373
assert.deepStrictEqual(actual.length, 0);
374
375
assert.ok(target1.calledOnce);
376
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
377
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions.length, 2);
378
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].identifier, extension1.identifier);
379
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].version, extension1.manifest.version);
380
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].location.toString(), extension1.location.toString());
381
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[1].identifier, extension2.identifier);
382
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[1].version, extension2.manifest.version);
383
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[1].location.toString(), extension2.location.toString());
384
385
assert.ok(target2.calledOnce);
386
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
387
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions.length, 2);
388
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].identifier, extension1.identifier);
389
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].version, extension1.manifest.version);
390
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].location.toString(), extension1.location.toString());
391
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[1].identifier, extension2.identifier);
392
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[1].version, extension2.manifest.version);
393
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[1].location.toString(), extension2.location.toString());
394
});
395
396
test('add extension with same id but different version', async () => {
397
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
398
399
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
400
401
const extension1 = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0'));
402
await testObject.addExtensionsToProfile([[extension1, undefined]], extensionsManifest);
403
404
const target1 = sinon.stub();
405
const target2 = sinon.stub();
406
const target3 = sinon.stub();
407
const target4 = sinon.stub();
408
disposables.add(testObject.onAddExtensions(target1));
409
disposables.add(testObject.onRemoveExtensions(target2));
410
disposables.add(testObject.onDidAddExtensions(target3));
411
disposables.add(testObject.onDidRemoveExtensions(target4));
412
const extension2 = aExtension('pub.a', joinPath(ROOT, 'pub.a-2.0.0'), undefined, { version: '2.0.0' });
413
await testObject.addExtensionsToProfile([[extension2, undefined]], extensionsManifest);
414
415
const actual = await testObject.scanProfileExtensions(extensionsManifest);
416
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension2.identifier, location: extension2.location.toJSON(), version: extension2.manifest.version, metadata: undefined }]);
417
418
assert.ok(target1.calledOnce);
419
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
420
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions.length, 1);
421
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].identifier, extension2.identifier);
422
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].version, extension2.manifest.version);
423
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].location.toString(), extension2.location.toString());
424
425
assert.ok(target2.calledOnce);
426
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
427
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions.length, 1);
428
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].identifier, extension1.identifier);
429
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].version, extension1.manifest.version);
430
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].location.toString(), extension1.location.toString());
431
432
assert.ok(target3.calledOnce);
433
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
434
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions.length, 1);
435
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].identifier, extension2.identifier);
436
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].version, extension2.manifest.version);
437
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].location.toString(), extension2.location.toString());
438
439
assert.ok(target4.calledOnce);
440
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
441
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions.length, 1);
442
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].identifier, extension1.identifier);
443
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].version, extension1.manifest.version);
444
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].location.toString(), extension1.location.toString());
445
});
446
447
test('add same extension', async () => {
448
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
449
450
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
451
452
const extension = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0'));
453
await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest);
454
455
const target1 = sinon.stub();
456
const target2 = sinon.stub();
457
const target3 = sinon.stub();
458
const target4 = sinon.stub();
459
disposables.add(testObject.onAddExtensions(target1));
460
disposables.add(testObject.onRemoveExtensions(target2));
461
disposables.add(testObject.onDidAddExtensions(target3));
462
disposables.add(testObject.onDidRemoveExtensions(target4));
463
await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest);
464
465
const actual = await testObject.scanProfileExtensions(extensionsManifest);
466
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]);
467
assert.ok(target1.notCalled);
468
assert.ok(target2.notCalled);
469
assert.ok(target3.notCalled);
470
assert.ok(target4.notCalled);
471
});
472
473
test('add same extension with different metadata', async () => {
474
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
475
476
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
477
478
const extension = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0'));
479
await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest);
480
481
const target1 = sinon.stub();
482
const target2 = sinon.stub();
483
const target3 = sinon.stub();
484
const target4 = sinon.stub();
485
disposables.add(testObject.onAddExtensions(target1));
486
disposables.add(testObject.onRemoveExtensions(target2));
487
disposables.add(testObject.onDidAddExtensions(target3));
488
disposables.add(testObject.onDidRemoveExtensions(target4));
489
await testObject.addExtensionsToProfile([[extension, { isApplicationScoped: true }]], extensionsManifest);
490
491
const actual = await testObject.scanProfileExtensions(extensionsManifest);
492
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON(), metadata: a.metadata })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: { isApplicationScoped: true } }]);
493
assert.ok(target1.notCalled);
494
assert.ok(target2.notCalled);
495
assert.ok(target3.notCalled);
496
assert.ok(target4.notCalled);
497
});
498
499
test('add extension with different version and metadata', async () => {
500
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
501
502
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
503
504
const extension1 = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0'));
505
await testObject.addExtensionsToProfile([[extension1, undefined]], extensionsManifest);
506
const extension2 = aExtension('pub.a', joinPath(ROOT, 'pub.a-2.0.0'), undefined, { version: '2.0.0' });
507
508
const target1 = sinon.stub();
509
const target2 = sinon.stub();
510
const target3 = sinon.stub();
511
const target4 = sinon.stub();
512
disposables.add(testObject.onAddExtensions(target1));
513
disposables.add(testObject.onRemoveExtensions(target2));
514
disposables.add(testObject.onDidAddExtensions(target3));
515
disposables.add(testObject.onDidRemoveExtensions(target4));
516
await testObject.addExtensionsToProfile([[extension2, { isApplicationScoped: true }]], extensionsManifest);
517
518
const actual = await testObject.scanProfileExtensions(extensionsManifest);
519
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON(), metadata: a.metadata })), [{ identifier: extension2.identifier, location: extension2.location.toJSON(), version: extension2.manifest.version, metadata: { isApplicationScoped: true } }]);
520
521
assert.ok(target1.calledOnce);
522
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
523
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions.length, 1);
524
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].identifier, extension2.identifier);
525
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].version, extension2.manifest.version);
526
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].location.toString(), extension2.location.toString());
527
528
assert.ok(target2.calledOnce);
529
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
530
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions.length, 1);
531
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].identifier, extension1.identifier);
532
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].version, extension1.manifest.version);
533
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].location.toString(), extension1.location.toString());
534
535
assert.ok(target3.calledOnce);
536
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
537
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions.length, 1);
538
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].identifier, extension2.identifier);
539
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].version, extension2.manifest.version);
540
assert.deepStrictEqual((<ProfileExtensionsEvent>(target1.args[0][0])).extensions[0].location.toString(), extension2.location.toString());
541
542
assert.ok(target4.calledOnce);
543
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).profileLocation.toString(), extensionsManifest.toString());
544
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions.length, 1);
545
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].identifier, extension1.identifier);
546
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].version, extension1.manifest.version);
547
assert.deepStrictEqual((<ProfileExtensionsEvent>(target2.args[0][0])).extensions[0].location.toString(), extension1.location.toString());
548
});
549
550
test('add extension with same id and version located in the different folder', async () => {
551
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
552
553
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
554
555
let extension = aExtension('pub.a', joinPath(ROOT, 'foo', 'pub.a-1.0.0'));
556
await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest);
557
558
const target1 = sinon.stub();
559
const target2 = sinon.stub();
560
const target3 = sinon.stub();
561
const target4 = sinon.stub();
562
disposables.add(testObject.onAddExtensions(target1));
563
disposables.add(testObject.onRemoveExtensions(target2));
564
disposables.add(testObject.onDidAddExtensions(target3));
565
disposables.add(testObject.onDidRemoveExtensions(target4));
566
extension = aExtension('pub.a', joinPath(ROOT, 'pub.a-1.0.0'));
567
await testObject.addExtensionsToProfile([[extension, undefined]], extensionsManifest);
568
569
const actual = await testObject.scanProfileExtensions(extensionsManifest);
570
assert.deepStrictEqual(actual.map(a => ({ ...a, location: a.location.toJSON() })), [{ identifier: extension.identifier, location: extension.location.toJSON(), version: extension.manifest.version, metadata: undefined }]);
571
assert.ok(target1.notCalled);
572
assert.ok(target2.notCalled);
573
assert.ok(target3.notCalled);
574
assert.ok(target4.notCalled);
575
});
576
577
test('read extension when uuid is different in identifier and manifest', async () => {
578
const extensionsManifest = joinPath(extensionsLocation, 'extensions.json');
579
await instantiationService.get(IFileService).writeFile(extensionsManifest, VSBuffer.fromString(JSON.stringify([{
580
identifier: {
581
id: 'pub.a',
582
uuid: 'uuid1`'
583
},
584
version: '1.0.0',
585
location: joinPath(extensionsLocation, 'pub.a-1.0.0').toString(),
586
relativeLocation: 'pub.a-1.0.0',
587
metadata: {
588
id: 'uuid',
589
}
590
}])));
591
592
const testObject = disposables.add(instantiationService.createInstance(TestObject, extensionsLocation));
593
const actual = await testObject.scanProfileExtensions(extensionsManifest);
594
assert.deepStrictEqual(actual.length, 1);
595
assert.deepStrictEqual(actual[0].identifier.id, 'pub.a');
596
assert.deepStrictEqual(actual[0].identifier.uuid, 'uuid');
597
});
598
599
function aExtension(id: string, location: URI, e?: Partial<IExtension>, manifest?: Partial<IExtensionManifest>): IExtension {
600
return {
601
identifier: { id },
602
location,
603
type: ExtensionType.User,
604
targetPlatform: TargetPlatform.DARWIN_X64,
605
isBuiltin: false,
606
manifest: {
607
name: 'name',
608
publisher: 'publisher',
609
version: '1.0.0',
610
engines: { vscode: '1.0.0' },
611
...manifest,
612
},
613
isValid: true,
614
preRelease: false,
615
validations: [],
616
...e
617
};
618
}
619
620
});
621
622