debt - dispose things in my unit tests (#192112)

* debt - dispose in `WorkingCopyHistoryTracker`

* adopt more

* more

* more

* more

* fix

* fix

* input

* input

* input

* input

* input

* input

* input

* input

* wtf

* .

* .

* inp

* .

* fix compile error

* fux

* give up

* fixup disposable

* testing: fix cannot read properties of undefined (reading 'layout') (#192340)

Fixes #189326

* input

---------

Co-authored-by: Connor Peet <connor@peet.io>
This commit is contained in:
Benjamin Pasero
2023-09-07 09:30:19 +02:00
committed by GitHub
co-authored by Connor Peet
parent 744cb4af36
commit 8adddf5d48
62 changed files with 755 additions and 747 deletions
+4
View File
@@ -622,11 +622,15 @@ export function peekStream<T>(stream: ReadableStream<T>, maxChunks: number): Pro
// Error Listener
const errorListener = (error: Error) => {
streamListeners.dispose();
return reject(error);
};
// End Listener
const endListener = () => {
streamListeners.dispose();
return resolve({ stream, buffer, ended: true });
};
+1 -1
View File
@@ -1395,7 +1395,7 @@ export class SearchData {
/**
* @internal
*/
export interface ITextBuffer extends IReadonlyTextBuffer {
export interface ITextBuffer extends IReadonlyTextBuffer, IDisposable {
setEOL(newEOL: '\r\n' | '\n'): void;
applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean, computeUndoEdits: boolean): ApplyEditsResult;
}
+4 -1
View File
@@ -537,7 +537,7 @@ export class FileService extends Disposable implements IFileService {
// validate read operation
const statPromise = this.validateReadFile(resource, options).then(stat => stat, error => {
cancellableSource.cancel();
cancellableSource.dispose(true);
throw error;
});
@@ -572,6 +572,9 @@ export class FileService extends Disposable implements IFileService {
fileStream = this.readFileBuffered(provider, resource, cancellableSource.token, options);
}
fileStream.on('end', () => cancellableSource.dispose());
fileStream.on('error', () => cancellableSource.dispose());
const fileStat = await statPromise;
return {
@@ -122,7 +122,7 @@ abstract class BaseStorageMain extends Disposable implements IStorageMain {
private readonly _onDidCloseStorage = this._register(new Emitter<void>());
readonly onDidCloseStorage = this._onDidCloseStorage.event;
private _storage = new Storage(new InMemoryStorageDatabase(), { hint: StorageHint.STORAGE_IN_MEMORY }); // storage is in-memory until initialized
private _storage = this._register(new Storage(new InMemoryStorageDatabase(), { hint: StorageHint.STORAGE_IN_MEMORY })); // storage is in-memory until initialized
get storage(): IStorage { return this._storage; }
abstract get path(): string | undefined;
@@ -155,7 +155,7 @@ abstract class BaseStorageMain extends Disposable implements IStorageMain {
try {
// Create storage via subclasses
const storage = await this.doCreate();
const storage = this._register(await this.doCreate());
// Replace our in-memory storage with the real
// once as soon as possible without awaiting
@@ -164,16 +164,16 @@ export class StorageMainService extends Disposable implements IStorageMainServic
//#region Application Storage
readonly applicationStorage = this.createApplicationStorage();
readonly applicationStorage = this._register(this.createApplicationStorage());
private createApplicationStorage(): IStorageMain {
this.logService.trace(`StorageMainService: creating application storage`);
const applicationStorage = new ApplicationStorageMain(this.getStorageOptions(), this.userDataProfilesService, this.logService, this.fileService);
once(applicationStorage.onDidCloseStorage)(() => {
this._register(once(applicationStorage.onDidCloseStorage)(() => {
this.logService.trace(`StorageMainService: closed application storage`);
});
}));
return applicationStorage;
}
@@ -193,7 +193,7 @@ export class StorageMainService extends Disposable implements IStorageMainServic
if (!profileStorage) {
this.logService.trace(`StorageMainService: creating profile storage (${profile.name})`);
profileStorage = this.createProfileStorage(profile);
profileStorage = this._register(this.createProfileStorage(profile));
this.mapProfileToStorage.set(profile.id, profileStorage);
const listener = this._register(profileStorage.onDidChangeStorage(e => this._onDidChangeProfileStorage.fire({
@@ -202,12 +202,12 @@ export class StorageMainService extends Disposable implements IStorageMainServic
profile
})));
once(profileStorage.onDidCloseStorage)(() => {
this._register(once(profileStorage.onDidCloseStorage)(() => {
this.logService.trace(`StorageMainService: closed profile storage (${profile.name})`);
this.mapProfileToStorage.delete(profile.id);
listener.dispose();
});
}));
}
return profileStorage;
@@ -238,14 +238,14 @@ export class StorageMainService extends Disposable implements IStorageMainServic
if (!workspaceStorage) {
this.logService.trace(`StorageMainService: creating workspace storage (${workspace.id})`);
workspaceStorage = this.createWorkspaceStorage(workspace);
workspaceStorage = this._register(this.createWorkspaceStorage(workspace));
this.mapWorkspaceToStorage.set(workspace.id, workspaceStorage);
once(workspaceStorage.onDidCloseStorage)(() => {
this._register(once(workspaceStorage.onDidCloseStorage)(() => {
this.logService.trace(`StorageMainService: closed workspace storage (${workspace.id})`);
this.mapWorkspaceToStorage.delete(workspace.id);
});
}));
}
return workspaceStorage;
@@ -11,11 +11,14 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
let storageService: T;
const disposables = new DisposableStore();
setup(async () => {
storageService = await params.setup();
});
teardown(() => {
disposables.clear();
return params.teardown(storageService);
});
@@ -33,7 +36,7 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
test('Storage change source', () => {
const storageValueChangeEvents: IStorageValueChangeEvent[] = [];
storageService.onDidChangeValue(StorageScope.WORKSPACE, undefined, new DisposableStore())(e => storageValueChangeEvents.push(e));
storageService.onDidChangeValue(StorageScope.WORKSPACE, undefined, disposables)(e => storageValueChangeEvents.push(e), undefined, disposables);
// Explicit external source
storageService.storeAll([{ key: 'testExternalChange', value: 'foobar', scope: StorageScope.WORKSPACE, target: StorageTarget.MACHINE }], true);
@@ -52,7 +55,7 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
test('Storage change event scope (all keys)', () => {
const storageValueChangeEvents: IStorageValueChangeEvent[] = [];
storageService.onDidChangeValue(StorageScope.WORKSPACE, undefined, new DisposableStore())(e => storageValueChangeEvents.push(e));
storageService.onDidChangeValue(StorageScope.WORKSPACE, undefined, disposables)(e => storageValueChangeEvents.push(e), undefined, disposables);
storageService.store('testChange', 'foobar', StorageScope.WORKSPACE, StorageTarget.MACHINE);
storageService.store('testChange2', 'foobar', StorageScope.WORKSPACE, StorageTarget.MACHINE);
@@ -64,7 +67,7 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
test('Storage change event scope (specific key)', () => {
const storageValueChangeEvents: IStorageValueChangeEvent[] = [];
storageService.onDidChangeValue(StorageScope.WORKSPACE, 'testChange', new DisposableStore())(e => storageValueChangeEvents.push(e));
storageService.onDidChangeValue(StorageScope.WORKSPACE, 'testChange', disposables)(e => storageValueChangeEvents.push(e), undefined, disposables);
storageService.store('testChange', 'foobar', StorageScope.WORKSPACE, StorageTarget.MACHINE);
storageService.store('testChange', 'foobar', StorageScope.PROFILE, StorageTarget.USER);
@@ -77,7 +80,7 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
function storeData(scope: StorageScope): void {
let storageValueChangeEvents: IStorageValueChangeEvent[] = [];
storageService.onDidChangeValue(scope, undefined, new DisposableStore())(e => storageValueChangeEvents.push(e));
storageService.onDidChangeValue(scope, undefined, disposables)(e => storageValueChangeEvents.push(e), undefined, disposables);
strictEqual(storageService.get('test.get', scope, 'foobar'), 'foobar');
strictEqual(storageService.get('test.get', scope, ''), '');
@@ -153,7 +156,7 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
function removeData(scope: StorageScope): void {
const storageValueChangeEvents: IStorageValueChangeEvent[] = [];
storageService.onDidChangeValue(scope, undefined, new DisposableStore())(e => storageValueChangeEvents.push(e));
storageService.onDidChangeValue(scope, undefined, disposables)(e => storageValueChangeEvents.push(e), undefined, disposables);
storageService.store('test.remove', 'foobar', scope, StorageTarget.MACHINE);
strictEqual('foobar', storageService.get('test.remove', scope, (undefined)!));
@@ -167,7 +170,7 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
test('Keys (in-memory)', () => {
let storageTargetEvent: IStorageTargetChangeEvent | undefined = undefined;
storageService.onDidChangeTarget(e => storageTargetEvent = e);
storageService.onDidChangeTarget(e => storageTargetEvent = e, undefined, disposables);
// Empty
for (const scope of [StorageScope.WORKSPACE, StorageScope.PROFILE, StorageScope.APPLICATION]) {
@@ -180,7 +183,7 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
// Add values
for (const scope of [StorageScope.WORKSPACE, StorageScope.PROFILE, StorageScope.APPLICATION]) {
storageService.onDidChangeValue(scope, undefined, new DisposableStore())(e => storageValueChangeEvent = e);
storageService.onDidChangeValue(scope, undefined, disposables)(e => storageValueChangeEvent = e, undefined, disposables);
for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) {
storageTargetEvent = Object.create(null);
@@ -24,9 +24,13 @@ import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentitySe
import { IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { UserDataProfilesMainService } from 'vs/platform/userDataProfile/electron-main/userDataProfile';
import { TestLifecycleMainService } from 'vs/platform/test/electron-main/workbenchTestServices';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { DisposableStore } from 'vs/base/common/lifecycle';
suite('StorageMainService', function () {
const disposables = new DisposableStore();
const productService: IProductService = { _serviceBrand: undefined, ...product };
const inMemoryProfileRoot = URI.file('/location').with({ scheme: Schemas.inMemory });
@@ -68,12 +72,12 @@ suite('StorageMainService', function () {
}
let storageChangeEvent: IStorageChangeEvent | undefined = undefined;
const storageChangeListener = storage.onDidChangeStorage(e => {
disposables.add(storage.onDidChangeStorage(e => {
storageChangeEvent = e;
});
}));
let storageDidClose = false;
const storageCloseListener = storage.onDidCloseStorage(() => storageDidClose = true);
disposables.add(storage.onDidCloseStorage(() => storageDidClose = true));
// Basic store/get/remove
const size = storage.items.size;
@@ -101,15 +105,21 @@ suite('StorageMainService', function () {
await storage.close();
strictEqual(storageDidClose, true);
storageChangeListener.dispose();
storageCloseListener.dispose();
}
teardown(() => {
disposables.clear();
});
function createStorageService(lifecycleMainService: ILifecycleMainService = new TestLifecycleMainService()): TestStorageMainService {
const environmentService = new NativeEnvironmentService(parseArgs(process.argv, OPTIONS), productService);
const fileService = new FileService(new NullLogService());
return new TestStorageMainService(new NullLogService(), environmentService, new UserDataProfilesMainService(new StateService(SaveStrategy.DELAYED, environmentService, new NullLogService(), fileService), new UriIdentityService(fileService), environmentService, fileService, new NullLogService()), lifecycleMainService, fileService, new UriIdentityService(fileService));
const fileService = disposables.add(new FileService(new NullLogService()));
const uriIdentityService = disposables.add(new UriIdentityService(fileService));
const testStorageService = disposables.add(new TestStorageMainService(new NullLogService(), environmentService, disposables.add(new UserDataProfilesMainService(new StateService(SaveStrategy.DELAYED, environmentService, new NullLogService(), fileService), disposables.add(uriIdentityService), environmentService, fileService, new NullLogService())), lifecycleMainService, fileService, uriIdentityService));
disposables.add(testStorageService.applicationStorage);
return testStorageService;
}
test('basics (application)', function () {
@@ -141,21 +151,21 @@ suite('StorageMainService', function () {
const workspaceStorage = storageMainService.workspaceStorage(workspace);
let didCloseWorkspaceStorage = false;
workspaceStorage.onDidCloseStorage(() => {
disposables.add(workspaceStorage.onDidCloseStorage(() => {
didCloseWorkspaceStorage = true;
});
}));
const profileStorage = storageMainService.profileStorage(profile);
let didCloseProfileStorage = false;
profileStorage.onDidCloseStorage(() => {
disposables.add(profileStorage.onDidCloseStorage(() => {
didCloseProfileStorage = true;
});
}));
const applicationStorage = storageMainService.applicationStorage;
let didCloseApplicationStorage = false;
applicationStorage.onDidCloseStorage(() => {
disposables.add(applicationStorage.onDidCloseStorage(() => {
didCloseApplicationStorage = true;
});
}));
strictEqual(applicationStorage, storageMainService.applicationStorage); // same instance as long as not closed
strictEqual(profileStorage, storageMainService.profileStorage(profile)); // same instance as long as not closed
@@ -177,7 +187,7 @@ suite('StorageMainService', function () {
const workspaceStorage2 = storageMainService.workspaceStorage(workspace);
notStrictEqual(workspaceStorage, workspaceStorage2);
return workspaceStorage2.close();
await workspaceStorage2.close();
});
test('storage closed before init works', async function () {
@@ -187,21 +197,21 @@ suite('StorageMainService', function () {
const workspaceStorage = storageMainService.workspaceStorage(workspace);
let didCloseWorkspaceStorage = false;
workspaceStorage.onDidCloseStorage(() => {
disposables.add(workspaceStorage.onDidCloseStorage(() => {
didCloseWorkspaceStorage = true;
});
}));
const profileStorage = storageMainService.profileStorage(profile);
let didCloseProfileStorage = false;
profileStorage.onDidCloseStorage(() => {
disposables.add(profileStorage.onDidCloseStorage(() => {
didCloseProfileStorage = true;
});
}));
const applicationStorage = storageMainService.applicationStorage;
let didCloseApplicationStorage = false;
applicationStorage.onDidCloseStorage(() => {
disposables.add(applicationStorage.onDidCloseStorage(() => {
didCloseApplicationStorage = true;
});
}));
await applicationStorage.close();
await profileStorage.close();
@@ -219,21 +229,21 @@ suite('StorageMainService', function () {
const workspaceStorage = storageMainService.workspaceStorage(workspace);
let didCloseWorkspaceStorage = false;
workspaceStorage.onDidCloseStorage(() => {
disposables.add(workspaceStorage.onDidCloseStorage(() => {
didCloseWorkspaceStorage = true;
});
}));
const profileStorage = storageMainService.profileStorage(profile);
let didCloseProfileStorage = false;
profileStorage.onDidCloseStorage(() => {
disposables.add(profileStorage.onDidCloseStorage(() => {
didCloseProfileStorage = true;
});
}));
const applicationtorage = storageMainService.applicationStorage;
let didCloseApplicationStorage = false;
applicationtorage.onDidCloseStorage(() => {
disposables.add(applicationtorage.onDidCloseStorage(() => {
didCloseApplicationStorage = true;
});
}));
applicationtorage.init();
profileStorage.init();
@@ -247,4 +257,6 @@ suite('StorageMainService', function () {
strictEqual(didCloseProfileStorage, true);
strictEqual(didCloseWorkspaceStorage, true);
});
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -191,7 +191,7 @@ export class EditorAutoSave extends Disposable implements IWorkbenchContribution
const handle = setTimeout(() => {
// Clear disposable
this.pendingAutoSavesAfterDelay.delete(workingCopy);
this.discardAutoSave(workingCopy);
// Save if dirty
if (workingCopy.isDirty()) {
@@ -808,13 +808,13 @@ export class TabsTitleControl extends TitleControl {
const tabActionRunner = new EditorCommandsContextActionRunner({ groupId: this.group.id, editorIndex: index });
const tabActionBar = new ActionBar(tabActionsContainer, { ariaLabel: localize('ariaLabelTabActions', "Tab actions"), actionRunner: tabActionRunner });
tabActionBar.onWillRun(e => {
const tabActionListener = tabActionBar.onWillRun(e => {
if (e.action.id === this.closeEditorAction.id) {
this.blockRevealActiveTabOnce();
}
});
const tabActionBarDisposable = combinedDisposable(tabActionBar, toDisposable(insert(this.tabActionBars, tabActionBar)));
const tabActionBarDisposable = combinedDisposable(tabActionBar, tabActionListener, toDisposable(insert(this.tabActionBars, tabActionBar)));
// Tab Border Bottom
const tabBorderBottomContainer = document.createElement('div');
@@ -25,7 +25,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { IExtensionService, toExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestContextService, TestWorkspaceTrustManagementService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestExtensionTipsService, TestSharedProcessService } from 'vs/workbench/test/electron-sandbox/workbenchTestServices';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
@@ -52,7 +52,6 @@ import { UserDataSyncEnablementService } from 'vs/platform/userDataSync/common/u
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust';
import { TestWorkspaceTrustManagementService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { platform } from 'vs/base/common/platform';
import { arch } from 'vs/base/common/process';
@@ -140,7 +139,7 @@ function setupTest() {
instantiationService.stub(IUserDataSyncEnablementService, instantiationService.createInstance(UserDataSyncEnablementService));
instantiationService.set(IExtensionsWorkbenchService, disposables.add(instantiationService.createInstance(ExtensionsWorkbenchService)));
instantiationService.stub(IWorkspaceTrustManagementService, new TestWorkspaceTrustManagementService());
instantiationService.stub(IWorkspaceTrustManagementService, disposables.add(new TestWorkspaceTrustManagementService()));
}
@@ -5,10 +5,10 @@
import * as assert from 'assert';
import { Event } from 'vs/base/common/event';
import { toResource } from 'vs/base/test/common/utils';
import { ensureNoDisposablesAreLeakedInTestSuite, toResource } from 'vs/base/test/common/utils';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { TestFilesConfigurationService, workbenchInstantiationService, TestServiceAccessor, registerTestFileEditor, createEditorPart, TestEnvironmentService, TestFileService } from 'vs/workbench/test/browser/workbenchTestServices';
import { IResolvedTextFileEditorModel, ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
import { ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager';
@@ -43,19 +43,19 @@ suite('EditorAutoSave', () => {
configurationService.setUserConfiguration('files', autoSaveConfig);
instantiationService.stub(IConfigurationService, configurationService);
instantiationService.stub(IFilesConfigurationService, new TestFilesConfigurationService(
instantiationService.stub(IFilesConfigurationService, disposables.add(new TestFilesConfigurationService(
<IContextKeyService>instantiationService.createInstance(MockContextKeyService),
configurationService,
new TestContextService(TestWorkspace),
TestEnvironmentService,
new UriIdentityService(new TestFileService()),
new TestFileService()
));
disposables.add(new UriIdentityService(disposables.add(new TestFileService()))),
disposables.add(new TestFileService())
)));
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
const editorService: EditorService = instantiationService.createInstance(EditorService);
const editorService: EditorService = disposables.add(instantiationService.createInstance(EditorService));
instantiationService.stub(IEditorService, editorService);
const accessor = instantiationService.createInstance(TestServiceAccessor);
@@ -71,14 +71,14 @@ suite('EditorAutoSave', () => {
const resource = toResource.call(this, '/path/index.txt');
const model = await accessor.textFileService.files.resolve(resource) as IResolvedTextFileEditorModel;
model.textEditorModel.setValue('Super Good');
const model: ITextFileEditorModel = disposables.add(await accessor.textFileService.files.resolve(resource));
model.textEditorModel?.setValue('Super Good');
assert.ok(model.isDirty());
await awaitModelSaved(model);
assert.ok(!model.isDirty());
assert.strictEqual(model.isDirty(), false);
});
test('editor auto saves on focus change if configured', async function () {
@@ -87,19 +87,23 @@ suite('EditorAutoSave', () => {
const resource = toResource.call(this, '/path/index.txt');
await accessor.editorService.openEditor({ resource, options: { override: DEFAULT_EDITOR_ASSOCIATION.id } });
const model = await accessor.textFileService.files.resolve(resource) as IResolvedTextFileEditorModel;
model.textEditorModel.setValue('Super Good');
const model: ITextFileEditorModel = disposables.add(await accessor.textFileService.files.resolve(resource));
model.textEditorModel?.setValue('Super Good');
assert.ok(model.isDirty());
await accessor.editorService.openEditor({ resource: toResource.call(this, '/path/index_other.txt') });
const editorPane = await accessor.editorService.openEditor({ resource: toResource.call(this, '/path/index_other.txt') });
await awaitModelSaved(model);
assert.ok(!model.isDirty());
assert.strictEqual(model.isDirty(), false);
await editorPane?.group?.closeAllEditors();
});
function awaitModelSaved(model: ITextFileEditorModel): Promise<void> {
return Event.toPromise(Event.once(model.onDidChangeDirty));
}
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -25,7 +25,7 @@ import { TextEditorService } from 'vs/workbench/services/textfile/common/textEdi
suite('Files - FileEditorInput', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
@@ -44,7 +44,6 @@ suite('Files - FileEditorInput', () => {
}
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService({
textEditorService: instantiationService => instantiationService.createInstance(TestTextEditorService)
}, disposables);
@@ -53,7 +52,7 @@ suite('Files - FileEditorInput', () => {
});
teardown(() => {
disposables.dispose();
disposables.clear();
});
test('Basics', async function () {
@@ -6,9 +6,9 @@
import * as assert from 'assert';
import { Event } from 'vs/base/common/event';
import { TextFileEditorTracker } from 'vs/workbench/contrib/files/browser/editors/textFileEditorTracker';
import { toResource } from 'vs/base/test/common/utils';
import { ensureNoDisposablesAreLeakedInTestSuite, toResource } from 'vs/base/test/common/utils';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { workbenchInstantiationService, TestServiceAccessor, TestFilesConfigurationService, registerTestFileEditor, registerTestResourceEditor, createEditorPart, TestEnvironmentService, TestFileService } from 'vs/workbench/test/browser/workbenchTestServices';
import { workbenchInstantiationService, TestServiceAccessor, TestFilesConfigurationService, registerTestFileEditor, registerTestResourceEditor, createEditorPart, TestEnvironmentService, TestFileService, workbenchTeardown } from 'vs/workbench/test/browser/workbenchTestServices';
import { IResolvedTextFileEditorModel, snapshotToString, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { FileChangesEvent, FileChangeType, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -25,8 +25,6 @@ import { IFilesConfigurationService } from 'vs/workbench/services/filesConfigura
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files';
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
import { TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace';
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
@@ -52,7 +50,7 @@ suite('Files - TextFileEditorTracker', () => {
disposables.clear();
});
async function createTracker(autoSaveEnabled = false): Promise<TestServiceAccessor> {
async function createTracker(autoSaveEnabled = false): Promise<{ accessor: TestServiceAccessor; cleanup: () => Promise<void> }> {
const instantiationService = workbenchInstantiationService(undefined, disposables);
if (autoSaveEnabled) {
@@ -61,22 +59,22 @@ suite('Files - TextFileEditorTracker', () => {
instantiationService.stub(IConfigurationService, configurationService);
instantiationService.stub(IFilesConfigurationService, new TestFilesConfigurationService(
const fileService = disposables.add(new TestFileService());
instantiationService.stub(IFilesConfigurationService, disposables.add(new TestFilesConfigurationService(
<IContextKeyService>instantiationService.createInstance(MockContextKeyService),
configurationService,
new TestContextService(TestWorkspace),
TestEnvironmentService,
new UriIdentityService(new TestFileService()),
new TestFileService()
));
disposables.add(new UriIdentityService(fileService)),
fileService
)));
}
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
instantiationService.stub(IWorkspaceTrustRequestService, new TestWorkspaceTrustRequestService(false));
const editorService: EditorService = instantiationService.createInstance(EditorService);
const editorService: EditorService = disposables.add(instantiationService.createInstance(EditorService));
disposables.add(editorService);
instantiationService.stub(IEditorService, editorService);
@@ -85,11 +83,16 @@ suite('Files - TextFileEditorTracker', () => {
disposables.add(instantiationService.createInstance(TestTextFileEditorTracker));
return accessor;
const cleanup = async () => {
await workbenchTeardown(instantiationService);
part.dispose();
};
return { accessor, cleanup };
}
test('file change event updates model', async function () {
const accessor = await createTracker();
const { accessor, cleanup } = await createTracker();
const resource = toResource.call(this, '/path/index.txt');
@@ -107,6 +110,8 @@ suite('Files - TextFileEditorTracker', () => {
await timeout(0); // due to event updating model async
assert.strictEqual(snapshotToString(model.createSnapshot()!), 'Hello Html');
await cleanup();
});
test('dirty text file model opens as editor', async function () {
@@ -134,7 +139,7 @@ suite('Files - TextFileEditorTracker', () => {
});
async function testDirtyTextFileModelOpensEditorDependingOnAutoSaveSetting(resource: URI, autoSave: boolean, error: boolean): Promise<void> {
const accessor = await createTracker(autoSave);
const { accessor, cleanup } = await createTracker(autoSave);
assert.ok(!accessor.editorService.isOpened({ resource, typeId: FILE_EDITOR_INPUT_ID, editorId: DEFAULT_EDITOR_ASSOCIATION.id }));
@@ -159,6 +164,8 @@ suite('Files - TextFileEditorTracker', () => {
await awaitEditorOpening(accessor.editorService);
assert.ok(accessor.editorService.isOpened({ resource, typeId: FILE_EDITOR_INPUT_ID, editorId: DEFAULT_EDITOR_ASSOCIATION.id }));
}
await cleanup();
}
test('dirty untitled text file model opens as editor', function () {
@@ -170,7 +177,7 @@ suite('Files - TextFileEditorTracker', () => {
});
async function testUntitledEditor(autoSaveEnabled: boolean): Promise<void> {
const accessor = await createTracker(autoSaveEnabled);
const { accessor, cleanup } = await createTracker(autoSaveEnabled);
const untitledTextEditor = await accessor.textEditorService.resolveTextEditor({ resource: undefined, forceUntitled: true }) as UntitledTextEditorInput;
const model = disposables.add(await untitledTextEditor.resolve());
@@ -181,6 +188,8 @@ suite('Files - TextFileEditorTracker', () => {
await awaitEditorOpening(accessor.editorService);
assert.ok(accessor.editorService.isOpened(untitledTextEditor));
await cleanup();
}
function awaitEditorOpening(editorService: IEditorService): Promise<void> {
@@ -188,7 +197,7 @@ suite('Files - TextFileEditorTracker', () => {
}
test('non-dirty files reload on window focus', async function () {
const accessor = await createTracker();
const { accessor, cleanup } = await createTracker();
const resource = toResource.call(this, '/path/index.txt');
@@ -198,6 +207,8 @@ suite('Files - TextFileEditorTracker', () => {
accessor.hostService.setFocus(true);
await awaitModelResolveEvent(accessor.textFileService, resource);
await cleanup();
});
function awaitModelResolveEvent(textFileService: ITextFileService, resource: URI): Promise<void> {
@@ -210,4 +221,6 @@ suite('Files - TextFileEditorTracker', () => {
});
});
}
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -58,9 +58,8 @@ import { NotebookOptions } from 'vs/workbench/contrib/notebook/browser/notebookO
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
import { IWorkingCopySaveEvent } from 'vs/workbench/services/workingCopy/common/workingCopy';
import { TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { TestLayoutService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestStorageService, TestWorkspaceTrustRequestService } from 'vs/workbench/test/common/workbenchTestServices';
import { FontInfo } from 'vs/editor/common/config/fontInfo';
import { EditorFontLigatures, EditorFontVariations } from 'vs/editor/common/config/editorOptions';
@@ -189,7 +188,7 @@ export function setupInstantiationService(disposables = new DisposableStore()) {
instantiationService.stub(ILogService, new NullLogService());
instantiationService.stub(IClipboardService, TestClipboardService);
instantiationService.stub(IStorageService, new TestStorageService());
instantiationService.stub(IWorkspaceTrustRequestService, new TestWorkspaceTrustRequestService(true));
instantiationService.stub(IWorkspaceTrustRequestService, disposables.add(new TestWorkspaceTrustRequestService(true)));
instantiationService.stub(INotebookExecutionStateService, new TestNotebookExecutionStateService());
instantiationService.stub(IKeybindingService, new MockKeybindingService());
instantiationService.stub(INotebookCellStatusBarService, new NotebookCellStatusBarService());
@@ -431,7 +431,7 @@ export class TestingExplorerView extends ViewPane {
this.dimensions.height = height;
this.dimensions.width = width;
this.container.style.height = `${height}px`;
this.viewModel.layout(height - this.treeHeader.clientHeight, width);
this.viewModel?.layout(height - this.treeHeader.clientHeight, width);
this.filter.value?.layout(width);
}
}
@@ -8,7 +8,7 @@ import { EditorActivation, IResourceEditorInput } from 'vs/platform/editor/commo
import { URI } from 'vs/base/common/uri';
import { Event } from 'vs/base/common/event';
import { DEFAULT_EDITOR_ASSOCIATION, EditorCloseContext, EditorsOrder, IEditorCloseEvent, EditorInputWithOptions, IEditorPane, IResourceDiffEditorInput, isEditorInputWithOptions, IUntitledTextResourceEditorInput, IUntypedEditorInput, SideBySideEditor, isEditorInput, EditorInputCapabilities } from 'vs/workbench/common/editor';
import { workbenchInstantiationService, TestServiceAccessor, registerTestEditor, TestFileEditorInput, ITestInstantiationService, registerTestResourceEditor, registerTestSideBySideEditor, createEditorPart, registerTestFileEditor, TestTextFileEditor, TestSingletonFileEditorInput } from 'vs/workbench/test/browser/workbenchTestServices';
import { workbenchInstantiationService, TestServiceAccessor, registerTestEditor, TestFileEditorInput, ITestInstantiationService, registerTestResourceEditor, registerTestSideBySideEditor, createEditorPart, registerTestFileEditor, TestTextFileEditor, TestSingletonFileEditorInput, workbenchTeardown } from 'vs/workbench/test/browser/workbenchTestServices';
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
import { IEditorGroup, IEditorGroupsService, GroupDirection, GroupsArrangement } from 'vs/workbench/services/editor/common/editorGroupsService';
import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart';
@@ -20,8 +20,7 @@ import { FileOperationEvent, FileOperation } from 'vs/platform/files/common/file
import { DisposableStore } from 'vs/base/common/lifecycle';
import { MockScopableContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { RegisteredEditorPriority } from 'vs/workbench/services/editor/common/editorResolverService';
import { IWorkspaceTrustRequestService, WorkspaceTrustUriResponse } from 'vs/platform/workspace/common/workspaceTrust';
import { TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { WorkspaceTrustUriResponse } from 'vs/platform/workspace/common/workspaceTrust';
import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { ErrorPlaceholderEditor } from 'vs/workbench/browser/parts/editor/editorPlaceholder';
@@ -50,9 +49,7 @@ suite('EditorService', () => {
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
instantiationService.stub(IWorkspaceTrustRequestService, new TestWorkspaceTrustRequestService(false));
const editorService = instantiationService.createInstance(EditorService);
const editorService = disposables.add(instantiationService.createInstance(EditorService));
instantiationService.stub(IEditorService, editorService);
return [part, editorService, instantiationService.createInstance(TestServiceAccessor)];
@@ -589,13 +586,7 @@ suite('EditorService', () => {
lastUntitledEditorFactoryEditor = undefined;
lastDiffEditorFactoryEditor = undefined;
for (const group of part.groups) {
await group.closeAllEditors();
}
for (const group of part.groups) {
accessor.editorGroupService.removeGroup(group);
}
await workbenchTeardown(accessor.instantiationService);
rootGroup = part.activeGroup;
}
@@ -30,12 +30,12 @@ import { IHostService } from 'vs/workbench/services/host/browser/host';
import { mock } from 'vs/base/test/common/mock';
import { IExtensionBisectService } from 'vs/workbench/services/extensionManagement/browser/extensionBisect';
import { IWorkspaceTrustManagementService, IWorkspaceTrustRequestService, WorkspaceTrustRequestOptions } from 'vs/platform/workspace/common/workspaceTrust';
import { TestWorkspaceTrustEnablementService, TestWorkspaceTrustManagementService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { ExtensionManifestPropertiesService, IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService';
import { TestContextService, TestProductService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestContextService, TestProductService, TestWorkspaceTrustEnablementService, TestWorkspaceTrustManagementService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace';
import { ExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagementService';
import { NullLogService } from 'vs/platform/log/common/log';
import { DisposableStore } from 'vs/base/common/lifecycle';
function createStorageService(instantiationService: TestInstantiationService): IStorageService {
let service = instantiationService.get(IStorageService);
@@ -70,7 +70,8 @@ export class TestExtensionEnablementService extends ExtensionEnablementService {
}, null, null));
const extensionManagementService = instantiationService.createInstance(ExtensionManagementService);
const workbenchExtensionManagementService = instantiationService.get(IWorkbenchExtensionManagementService) || instantiationService.stub(IWorkbenchExtensionManagementService, extensionManagementService);
const workspaceTrustManagementService = instantiationService.get(IWorkspaceTrustManagementService) || instantiationService.stub(IWorkspaceTrustManagementService, new TestWorkspaceTrustManagementService());
const disposables = new DisposableStore();
const workspaceTrustManagementService = instantiationService.get(IWorkspaceTrustManagementService) || instantiationService.stub(IWorkspaceTrustManagementService, disposables.add(new TestWorkspaceTrustManagementService()));
super(
storageService,
new GlobalExtensionEnablementService(storageService, extensionManagementService),
@@ -90,6 +91,7 @@ export class TestExtensionEnablementService extends ExtensionEnablementService {
instantiationService.get(IExtensionManifestPropertiesService) || instantiationService.stub(IExtensionManifestPropertiesService, new ExtensionManifestPropertiesService(TestProductService, new TestConfigurationService(), new TestWorkspaceTrustEnablementService(), new NullLogService())),
instantiationService
);
this._register(disposables);
}
public async waitUntilInitialized(): Promise<void> {
@@ -7,12 +7,11 @@ import * as assert from 'assert';
import { IExtensionManifest, ExtensionUntrustedWorkspaceSupportType } from 'vs/platform/extensions/common/extensions';
import { ExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { TestProductService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestProductService, TestWorkspaceTrustEnablementService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IProductService } from 'vs/platform/product/common/productService';
import { isWeb } from 'vs/base/common/platform';
import { TestWorkspaceTrustEnablementService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { IWorkspaceTrustEnablementService } from 'vs/platform/workspace/common/workspaceTrust';
import { NullLogService } from 'vs/platform/log/common/log';
@@ -40,7 +40,7 @@ suite('HistoryService', function () {
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
const editorService = instantiationService.createInstance(EditorService);
const editorService = disposables.add(instantiationService.createInstance(EditorService));
instantiationService.stub(IEditorService, editorService);
const configurationService = new TestConfigurationService();
@@ -12,7 +12,7 @@ import { workbenchInstantiationService } from 'vs/workbench/test/electron-sandbo
suite('Lifecycleservice', function () {
let lifecycleService: TestLifecycleService;
let disposables: DisposableStore;
const disposables = new DisposableStore();
class TestLifecycleService extends NativeLifecycleService {
@@ -26,14 +26,12 @@ suite('Lifecycleservice', function () {
}
setup(async () => {
disposables = new DisposableStore();
const instantiationService = workbenchInstantiationService(undefined, disposables);
lifecycleService = instantiationService.createInstance(TestLifecycleService);
});
teardown(async () => {
disposables.dispose();
disposables.clear();
});
test('onBeforeShutdown - final veto called after other vetos', async function () {
@@ -11,6 +11,7 @@ import { URI } from 'vs/base/common/uri';
import { IStorageChangeEvent, Storage } from 'vs/base/parts/storage/common/storage';
import { flakySuite } from 'vs/base/test/common/testUtils';
import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { FileService } from 'vs/platform/files/common/fileService';
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
import { NullLogService } from 'vs/platform/log/common/log';
@@ -49,7 +50,7 @@ async function createStorageService(): Promise<[DisposableStore, BrowserStorageS
cacheHome: joinPath(inMemoryExtraProfileRoot, 'cache')
};
const storageService = disposables.add(new BrowserStorageService({ id: 'workspace-storage-test' }, new UserDataProfileService(inMemoryExtraProfile, new UserDataProfilesService(TestEnvironmentService, fileService, new UriIdentityService(fileService), logService)), logService));
const storageService = disposables.add(new BrowserStorageService({ id: 'workspace-storage-test' }, disposables.add(new UserDataProfileService(inMemoryExtraProfile, new UserDataProfilesService(TestEnvironmentService, fileService, disposables.add(new UriIdentityService(fileService)), logService))), logService));
await storageService.initialize();
@@ -73,6 +74,8 @@ flakySuite('StorageService (browser)', function () {
disposables.clear();
}
});
ensureNoDisposablesAreLeakedInTestSuite();
});
flakySuite('StorageService (browser specific)', () => {
@@ -110,6 +113,8 @@ flakySuite('StorageService (browser specific)', () => {
}
});
});
ensureNoDisposablesAreLeakedInTestSuite();
});
flakySuite('IndexDBStorageDatabase (browser)', () => {
@@ -117,13 +122,17 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
const id = 'workspace-storage-db-test';
const logService = new NullLogService();
const disposables = new DisposableStore();
teardown(async () => {
const storage = await IndexedDBStorageDatabase.create({ id }, logService);
const storage = disposables.add(await IndexedDBStorageDatabase.create({ id }, logService));
await storage.clear();
disposables.clear();
});
test('Basics', async () => {
let storage = new Storage(await IndexedDBStorageDatabase.create({ id }, logService));
let storage = disposables.add(new Storage(disposables.add(await IndexedDBStorageDatabase.create({ id }, logService))));
await storage.init();
@@ -145,7 +154,7 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
await storage.close();
storage = new Storage(await IndexedDBStorageDatabase.create({ id }, logService));
storage = disposables.add(new Storage(disposables.add(await IndexedDBStorageDatabase.create({ id }, logService))));
await storage.init();
@@ -168,7 +177,7 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
await storage.close();
storage = new Storage(await IndexedDBStorageDatabase.create({ id }, logService));
storage = disposables.add(new Storage(disposables.add(await IndexedDBStorageDatabase.create({ id }, logService))));
await storage.init();
@@ -196,7 +205,7 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
await storage.close();
storage = new Storage(await IndexedDBStorageDatabase.create({ id }, logService));
storage = disposables.add(new Storage(disposables.add(await IndexedDBStorageDatabase.create({ id }, logService))));
await storage.init();
@@ -209,7 +218,7 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
});
test('Clear', async () => {
let storage = new Storage(await IndexedDBStorageDatabase.create({ id }, logService));
let storage = disposables.add(new Storage(disposables.add(await IndexedDBStorageDatabase.create({ id }, logService))));
await storage.init();
@@ -219,13 +228,13 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
await storage.close();
const db = await IndexedDBStorageDatabase.create({ id }, logService);
storage = new Storage(db);
const db = disposables.add(await IndexedDBStorageDatabase.create({ id }, logService));
storage = disposables.add(new Storage(db));
await storage.init();
await db.clear();
storage = new Storage(await IndexedDBStorageDatabase.create({ id }, logService));
storage = disposables.add(new Storage(disposables.add(await IndexedDBStorageDatabase.create({ id }, logService))));
await storage.init();
@@ -238,7 +247,7 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
});
test('Inserts and Deletes at the same time', async () => {
let storage = new Storage(await IndexedDBStorageDatabase.create({ id }, logService));
let storage = disposables.add(new Storage(disposables.add(await IndexedDBStorageDatabase.create({ id }, logService))));
await storage.init();
@@ -248,7 +257,7 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
await storage.close();
storage = new Storage(await IndexedDBStorageDatabase.create({ id }, logService));
storage = disposables.add(new Storage(disposables.add(await IndexedDBStorageDatabase.create({ id }, logService))));
await storage.init();
@@ -260,7 +269,7 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
await storage.close();
storage = new Storage(await IndexedDBStorageDatabase.create({ id }, logService));
storage = disposables.add(new Storage(disposables.add(await IndexedDBStorageDatabase.create({ id }, logService))));
await storage.init();
@@ -271,9 +280,9 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
});
test('Storage change event', async () => {
const storage = new Storage(await IndexedDBStorageDatabase.create({ id }, logService));
const storage = disposables.add(new Storage(disposables.add(await IndexedDBStorageDatabase.create({ id }, logService))));
let storageChangeEvents: IStorageChangeEvent[] = [];
storage.onDidChangeStorage(e => storageChangeEvents.push(e));
disposables.add(storage.onDidChangeStorage(e => storageChangeEvents.push(e)));
await storage.init();
@@ -294,4 +303,6 @@ flakySuite('IndexDBStorageDatabase (browser)', () => {
storageValueChangeEvent = storageChangeEvents.find(e => e.key === 'isExternal');
strictEqual(storageValueChangeEvent?.external, true);
});
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -22,6 +22,7 @@ import { isWeb } from 'vs/base/common/platform';
import { IWorkingCopyFileService, WorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
import { WorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
// optimization: we don't need to run this suite in native environment,
// because we have nativeTextFileService.io.test.ts for it,
@@ -39,18 +40,17 @@ if (isWeb) {
const instantiationService = workbenchInstantiationService(undefined, disposables);
const logService = new NullLogService();
const fileService = new FileService(logService);
const fileService = disposables.add(new FileService(logService));
fileProvider = new TestInMemoryFileSystemProvider();
fileProvider = disposables.add(new TestInMemoryFileSystemProvider());
disposables.add(fileService.registerProvider(Schemas.file, fileProvider));
disposables.add(fileProvider);
const collection = new ServiceCollection();
collection.set(IFileService, fileService);
collection.set(IWorkingCopyFileService, disposables.add(new WorkingCopyFileService(fileService, disposables.add(new WorkingCopyService()), instantiationService, disposables.add(new UriIdentityService(fileService)))));
collection.set(IWorkingCopyFileService, new WorkingCopyFileService(fileService, new WorkingCopyService(), instantiationService, new UriIdentityService(fileService)));
service = instantiationService.createChild(collection).createInstance(TestBrowserTextFileServiceWithEncodingOverrides);
service = disposables.add(instantiationService.createChild(collection).createInstance(TestBrowserTextFileServiceWithEncodingOverrides));
disposables.add(<TextFileEditorModelManager>service.files);
await fileProvider.mkdir(URI.file(testDir));
for (const fileName in files) {
@@ -65,8 +65,6 @@ if (isWeb) {
},
teardown: async () => {
(<TextFileEditorModelManager>service.files).dispose();
disposables.clear();
},
@@ -111,5 +109,7 @@ if (isWeb) {
return null; // ignore errors (like file not found)
}
}
ensureNoDisposablesAreLeakedInTestSuite();
});
}
@@ -28,22 +28,21 @@ suite('Files - TextFileEditorModel', () => {
return stat ? stat.mtime : -1;
}
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
let content: string;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
content = accessor.fileService.getContent();
disposables.add(<TextFileEditorModelManager>accessor.textFileService.files);
});
teardown(() => {
(<TextFileEditorModelManager>accessor.textFileService.files).dispose();
accessor.fileService.setContent(content);
disposables.dispose();
disposables.clear();
});
test('basic events', async function () {
@@ -18,18 +18,17 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
suite('Files - TextFileEditorModelManager', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
});
teardown(() => {
disposables.dispose();
disposables.clear();
});
test('add, remove, clear, get, getAll', function () {
@@ -13,21 +13,20 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
suite('Files - TextFileService', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let model: TextFileEditorModel;
let accessor: TestServiceAccessor;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
disposables.add(<ITestTextFileEditorModelManager>accessor.textFileService.files);
});
teardown(() => {
model?.dispose();
(<ITestTextFileEditorModelManager>accessor.textFileService.files).dispose();
disposables.dispose();
disposables.clear();
});
test('isDirty/getDirty - files and untitled', async function () {
@@ -13,6 +13,7 @@ import { createTextModel } from 'vs/editor/test/common/testTextModel';
import { ITextSnapshot, DefaultEndOfLine } from 'vs/editor/common/model';
import { isWindows } from 'vs/base/common/platform';
import { createTextBufferFactoryFromStream } from 'vs/editor/common/model/textModel';
import { DisposableStore } from 'vs/base/common/lifecycle';
export interface Params {
setup(): Promise<{
@@ -40,6 +41,7 @@ export default function createSuite(params: Params) {
let service: ITextFileService;
let testDir = '';
const { exists, stat, readFile, detectEncodingByBOM } = params;
const disposables = new DisposableStore();
setup(async () => {
const result = await params.setup();
@@ -49,6 +51,7 @@ export default function createSuite(params: Params) {
teardown(async () => {
await params.teardown();
disposables.clear();
});
test('create - no encoding - content empty', async () => {
@@ -165,9 +168,9 @@ export default function createSuite(params: Params) {
});
function createTextModelSnapshot(text: string, preserveBOM?: boolean): ITextSnapshot {
const textModel = createTextModel(text);
const textModel = disposables.add(createTextModel(text));
const snapshot = textModel.createSnapshot(preserveBOM);
textModel.dispose();
return snapshot;
}
@@ -224,7 +227,8 @@ export default function createSuite(params: Params) {
const resolved = await service.readStream(resource);
assert.strictEqual(resolved.encoding, encoding);
assert.strictEqual(snapshotToString(resolved.value.create(isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).textBuffer.createSnapshot(false)), expectedContent);
const textBuffer = disposables.add(resolved.value.create(isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).textBuffer);
assert.strictEqual(snapshotToString(textBuffer.createSnapshot(false)), expectedContent);
}
test('write - use encoding (cp1252)', async () => {
@@ -252,18 +256,21 @@ export default function createSuite(params: Params) {
async function testEncodingKeepsData(resource: URI, encoding: string, expected: string) {
let resolved = await service.readStream(resource, { encoding });
const content = snapshotToString(resolved.value.create(isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).textBuffer.createSnapshot(false));
const textBuffer = disposables.add(resolved.value.create(isWindows ? DefaultEndOfLine.CRLF : DefaultEndOfLine.LF).textBuffer);
const content = snapshotToString(textBuffer.createSnapshot(false));
assert.strictEqual(content, expected);
await service.write(resource, content, { encoding });
resolved = await service.readStream(resource, { encoding });
assert.strictEqual(snapshotToString(resolved.value.create(DefaultEndOfLine.CRLF).textBuffer.createSnapshot(false)), content);
const textBuffer2 = disposables.add(resolved.value.create(DefaultEndOfLine.CRLF).textBuffer);
assert.strictEqual(snapshotToString(textBuffer2.createSnapshot(false)), content);
await service.write(resource, createTextModelSnapshot(content), { encoding });
resolved = await service.readStream(resource, { encoding });
assert.strictEqual(snapshotToString(resolved.value.create(DefaultEndOfLine.CRLF).textBuffer.createSnapshot(false)), content);
const textBuffer3 = disposables.add(resolved.value.create(DefaultEndOfLine.CRLF).textBuffer);
assert.strictEqual(snapshotToString(textBuffer3.createSnapshot(false)), content);
}
test('write - no encoding - content as string', async () => {
@@ -340,7 +347,7 @@ export default function createSuite(params: Params) {
let detectedEncoding = await detectEncodingByBOM(resource.fsPath);
assert.strictEqual(detectedEncoding, null);
const model = createTextModel((await readFile(resource.fsPath)).toString() + 'updates');
const model = disposables.add(createTextModel((await readFile(resource.fsPath)).toString() + 'updates'));
await service.write(resource, model.createSnapshot(), { encoding: UTF8_with_bom });
detectedEncoding = await detectEncodingByBOM(resource.fsPath);
@@ -360,8 +367,6 @@ export default function createSuite(params: Params) {
await service.write(resource, model.createSnapshot(), { encoding: UTF8 });
detectedEncoding = await detectEncodingByBOM(resource.fsPath);
assert.strictEqual(detectedEncoding, null);
model.dispose();
});
test('write - preserve UTF8 BOM - content as string', async () => {
@@ -412,8 +417,9 @@ export default function createSuite(params: Params) {
assert.strictEqual(result.size, (await stat(resource.fsPath)).size);
const content = (await readFile(resource.fsPath)).toString();
const textBuffer = disposables.add(result.value.create(DefaultEndOfLine.LF).textBuffer);
assert.strictEqual(
snapshotToString(result.value.create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false)),
snapshotToString(textBuffer.createSnapshot(false)),
snapshotToString(createTextModelSnapshot(content, false)));
}
@@ -541,7 +547,8 @@ export default function createSuite(params: Params) {
const result = await service.readStream(resource, { encoding });
assert.strictEqual(result.encoding, encoding);
let contents = snapshotToString(result.value.create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false));
const textBuffer = disposables.add(result.value.create(DefaultEndOfLine.LF).textBuffer);
let contents = snapshotToString(textBuffer.createSnapshot(false));
assert.strictEqual(contents.indexOf(needle), 0);
assert.ok(contents.indexOf(needle, 10) > 0);
@@ -557,7 +564,8 @@ export default function createSuite(params: Params) {
const factory = await createTextBufferFactoryFromStream(await service.getDecodedStream(resource, bufferToStream(rawFileVSBuffer), { encoding }));
contents = snapshotToString(factory.create(DefaultEndOfLine.LF).textBuffer.createSnapshot(false));
const textBuffer2 = disposables.add(factory.create(DefaultEndOfLine.LF).textBuffer);
contents = snapshotToString(textBuffer2.createSnapshot(false));
assert.strictEqual(contents.indexOf(needle), 0);
assert.ok(contents.indexOf(needle, 10) > 0);
@@ -35,18 +35,17 @@ suite('Files - NativeTextFileService i/o', function () {
const instantiationService = workbenchInstantiationService(undefined, disposables);
const logService = new NullLogService();
const fileService = new FileService(logService);
const fileService = disposables.add(new FileService(logService));
fileProvider = new TestInMemoryFileSystemProvider();
fileProvider = disposables.add(new TestInMemoryFileSystemProvider());
disposables.add(fileService.registerProvider(Schemas.file, fileProvider));
disposables.add(fileProvider);
const collection = new ServiceCollection();
collection.set(IFileService, fileService);
collection.set(IWorkingCopyFileService, disposables.add(new WorkingCopyFileService(fileService, disposables.add(new WorkingCopyService()), instantiationService, disposables.add(new UriIdentityService(fileService)))));
collection.set(IWorkingCopyFileService, new WorkingCopyFileService(fileService, new WorkingCopyService(), instantiationService, new UriIdentityService(fileService)));
service = instantiationService.createChild(collection).createInstance(TestNativeTextFileServiceWithEncodingOverrides);
service = disposables.add(instantiationService.createChild(collection).createInstance(TestNativeTextFileServiceWithEncodingOverrides));
disposables.add(<TextFileEditorModelManager>service.files);
await fileProvider.mkdir(URI.file(testDir));
for (const fileName in files) {
@@ -61,8 +60,6 @@ suite('Files - NativeTextFileService i/o', function () {
},
teardown: async () => {
(<TextFileEditorModelManager>service.files).dispose();
disposables.clear();
},
@@ -19,7 +19,7 @@ import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentitySe
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { toResource } from 'vs/base/test/common/utils';
import { ensureNoDisposablesAreLeakedInTestSuite, toResource } from 'vs/base/test/common/utils';
suite('Files - NativeTextFileService', function () {
const disposables = new DisposableStore();
@@ -31,28 +31,25 @@ suite('Files - NativeTextFileService', function () {
instantiationService = workbenchInstantiationService(undefined, disposables);
const logService = new NullLogService();
const fileService = new FileService(logService);
const fileService = disposables.add(new FileService(logService));
const fileProvider = new InMemoryFileSystemProvider();
const fileProvider = disposables.add(new InMemoryFileSystemProvider());
disposables.add(fileService.registerProvider(Schemas.file, fileProvider));
disposables.add(fileProvider);
const collection = new ServiceCollection();
collection.set(IFileService, fileService);
collection.set(IWorkingCopyFileService, disposables.add(new WorkingCopyFileService(fileService, disposables.add(new WorkingCopyService()), instantiationService, disposables.add(new UriIdentityService(fileService)))));
collection.set(IWorkingCopyFileService, new WorkingCopyFileService(fileService, new WorkingCopyService(), instantiationService, new UriIdentityService(fileService)));
service = instantiationService.createChild(collection).createInstance(TestNativeTextFileServiceWithEncodingOverrides);
service = disposables.add(instantiationService.createChild(collection).createInstance(TestNativeTextFileServiceWithEncodingOverrides));
disposables.add(<TextFileEditorModelManager>service.files);
});
teardown(() => {
(<TextFileEditorModelManager>service.files).dispose();
disposables.clear();
});
test('shutdown joins on pending saves', async function () {
const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined);
const model: TextFileEditorModel = disposables.add(instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined));
await model.resolve();
@@ -67,4 +64,6 @@ suite('Files - NativeTextFileService', function () {
assert.strictEqual(pendingSaveAwaited, true);
});
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -22,21 +22,18 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
suite('Workbench - TextModelResolverService', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
let model: TextFileEditorModel;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
disposables.add(<TextFileEditorModelManager>accessor.textFileService.files);
});
teardown(() => {
model?.dispose();
(<TextFileEditorModelManager>accessor.textFileService.files).dispose();
disposables.dispose();
disposables.clear();
});
test('resolve resource', async () => {
@@ -24,19 +24,18 @@ import { LanguageDetectionLanguageEventSource } from 'vs/workbench/services/lang
suite('Untitled text editors', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
disposables.add(accessor.untitledTextEditorService as UntitledTextEditorService);
});
teardown(() => {
(accessor.untitledTextEditorService as UntitledTextEditorService).dispose();
disposables.dispose();
disposables.clear();
});
test('basics', async () => {
@@ -116,7 +116,7 @@ export class WorkingCopyBackupsModel {
}
}
export abstract class WorkingCopyBackupService implements IWorkingCopyBackupService {
export abstract class WorkingCopyBackupService extends Disposable implements IWorkingCopyBackupService {
declare readonly _serviceBrand: undefined;
@@ -127,7 +127,9 @@ export abstract class WorkingCopyBackupService implements IWorkingCopyBackupServ
@IFileService protected fileService: IFileService,
@ILogService private readonly logService: ILogService
) {
this.impl = this.initialize(backupWorkspaceHome);
super();
this.impl = this._register(this.initialize(backupWorkspaceHome));
}
private initialize(backupWorkspaceHome: URI | undefined): WorkingCopyBackupServiceImpl | InMemoryWorkingCopyBackupService {
@@ -533,13 +535,15 @@ class WorkingCopyBackupServiceImpl extends Disposable implements IWorkingCopyBac
}
}
export class InMemoryWorkingCopyBackupService implements IWorkingCopyBackupService {
export class InMemoryWorkingCopyBackupService extends Disposable implements IWorkingCopyBackupService {
declare readonly _serviceBrand: undefined;
private backups = new ResourceMap<{ typeId: string; content: VSBuffer; meta?: IWorkingCopyBackupMeta }>();
constructor() { }
constructor() {
super();
}
async hasBackups(): Promise<boolean> {
return this.backups.size > 0;
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup';
import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { IWorkingCopy, IWorkingCopyIdentifier, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopy';
import { ILogService } from 'vs/platform/log/common/log';
@@ -56,8 +56,8 @@ export abstract class WorkingCopyBackupTracker extends Disposable {
this._register(this.workingCopyService.onDidChangeContent(workingCopy => this.onDidChangeContent(workingCopy)));
// Lifecycle
this.lifecycleService.onBeforeShutdown(event => (event as InternalBeforeShutdownEvent).finalVeto(() => this.onFinalBeforeShutdown(event.reason), 'veto.backups'));
this.lifecycleService.onWillShutdown(() => this.onWillShutdown());
this._register(this.lifecycleService.onBeforeShutdown(event => (event as InternalBeforeShutdownEvent).finalVeto(() => this.onFinalBeforeShutdown(event.reason), 'veto.backups')));
this._register(this.lifecycleService.onWillShutdown(() => this.onWillShutdown()));
// Once a handler registers, restore backups
this._register(this.workingCopyEditorService.onDidRegisterHandler(handler => this.restoreBackups(handler)));
@@ -103,8 +103,8 @@ export abstract class WorkingCopyBackupTracker extends Disposable {
// A map of scheduled pending backup operations for working copies
// Given https://github.com/microsoft/vscode/issues/158038, we explicitly
// do not store `IWorkingCopy` but the identifier in the map, since it
// looks like GC is not runnin for the working copy otherwise.
protected readonly pendingBackupOperations = new Map<IWorkingCopyIdentifier, IDisposable>();
// looks like GC is not running for the working copy otherwise.
protected readonly pendingBackupOperations = new Map<IWorkingCopyIdentifier, { disposable: IDisposable; cancel: () => void }>();
private suspended = false;
@@ -206,17 +206,22 @@ export abstract class WorkingCopyBackupTracker extends Disposable {
// Clear disposable unless we got canceled which would
// indicate another operation has started meanwhile
if (!cts.token.isCancellationRequested) {
this.pendingBackupOperations.delete(workingCopyIdentifier);
this.doClearPendingBackupOperation(workingCopyIdentifier);
}
}, this.getBackupScheduleDelay(workingCopy));
// Keep in map for disposal as needed
this.pendingBackupOperations.set(workingCopyIdentifier, toDisposable(() => {
this.logService.trace(`[backup tracker] clearing pending backup creation`, workingCopy.resource.toString(), workingCopy.typeId);
this.pendingBackupOperations.set(workingCopyIdentifier, {
cancel: () => {
this.logService.trace(`[backup tracker] clearing pending backup creation`, workingCopy.resource.toString(), workingCopy.typeId);
cts.dispose(true);
clearTimeout(handle);
}));
cts.cancel();
},
disposable: toDisposable(() => {
cts.dispose();
clearTimeout(handle);
})
});
}
protected getBackupScheduleDelay(workingCopy: IWorkingCopy): number {
@@ -247,11 +252,14 @@ export abstract class WorkingCopyBackupTracker extends Disposable {
this.doDiscardBackup(workingCopyIdentifier, cts);
// Keep in map for disposal as needed
this.pendingBackupOperations.set(workingCopyIdentifier, toDisposable(() => {
this.logService.trace(`[backup tracker] clearing pending backup discard`, workingCopy.resource.toString(), workingCopy.typeId);
this.pendingBackupOperations.set(workingCopyIdentifier, {
cancel: () => {
this.logService.trace(`[backup tracker] clearing pending backup discard`, workingCopy.resource.toString(), workingCopy.typeId);
cts.dispose(true);
}));
cts.cancel();
},
disposable: cts
});
}
private async doDiscardBackup(workingCopyIdentifier: IWorkingCopyIdentifier, cts: CancellationTokenSource) {
@@ -267,7 +275,7 @@ export abstract class WorkingCopyBackupTracker extends Disposable {
// Clear disposable unless we got canceled which would
// indicate another operation has started meanwhile
if (!cts.token.isCancellationRequested) {
this.pendingBackupOperations.delete(workingCopyIdentifier);
this.doClearPendingBackupOperation(workingCopyIdentifier);
}
}
@@ -287,14 +295,29 @@ export abstract class WorkingCopyBackupTracker extends Disposable {
}
if (workingCopyIdentifier) {
dispose(this.pendingBackupOperations.get(workingCopyIdentifier));
this.pendingBackupOperations.delete(workingCopyIdentifier);
this.doClearPendingBackupOperation(workingCopyIdentifier, { cancel: true });
}
}
private doClearPendingBackupOperation(workingCopyIdentifier: IWorkingCopyIdentifier, options?: { cancel: boolean }): void {
const pendingBackupOperation = this.pendingBackupOperations.get(workingCopyIdentifier);
if (!pendingBackupOperation) {
return;
}
if (options?.cancel) {
pendingBackupOperation.cancel();
}
pendingBackupOperation.disposable.dispose();
this.pendingBackupOperations.delete(workingCopyIdentifier);
}
protected cancelBackupOperations(): void {
for (const [, disposable] of this.pendingBackupOperations) {
dispose(disposable);
for (const [, operation] of this.pendingBackupOperations) {
operation.cancel();
operation.disposable.dispose();
}
this.pendingBackupOperations.clear();
@@ -814,7 +814,7 @@ export class NativeWorkingCopyHistoryService extends WorkingCopyHistoryService {
if (!this.isRemotelyStored) {
// Local: persist all on shutdown
this.lifecycleService.onWillShutdown(e => this.onWillShutdown(e));
this._register(this.lifecycleService.onWillShutdown(e => this.onWillShutdown(e)));
// Local: schedule persist on change
this._register(Event.any(this.onDidAddEntry, this.onDidChangeEntry, this.onDidReplaceEntry, this.onDidRemoveEntry)(() => this.onDidChangeModels()));
@@ -34,7 +34,7 @@ export class NativeWorkingCopyBackupService extends WorkingCopyBackupService {
// Lifecycle: ensure to prolong the shutdown for as long
// as pending backup operations have not finished yet.
// Otherwise, we risk writing partial backups to disk.
this.lifecycleService.onWillShutdown(event => event.join(this.joinBackups(), { id: 'join.workingCopyBackups', label: localize('join.workingCopyBackups', "Backup working copies") }));
this._register(this.lifecycleService.onWillShutdown(event => event.join(this.joinBackups(), { id: 'join.workingCopyBackups', label: localize('join.workingCopyBackups', "Backup working copies") })));
}
}
@@ -18,21 +18,20 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
suite('FileWorkingCopyManager', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
let manager: IFileWorkingCopyManager<TestStoredFileWorkingCopyModel, TestUntitledFileWorkingCopyModel>;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
accessor.fileService.registerProvider(Schemas.file, new TestInMemoryFileSystemProvider());
accessor.fileService.registerProvider(Schemas.vscodeRemote, new TestInMemoryFileSystemProvider());
manager = new FileWorkingCopyManager(
manager = disposables.add(new FileWorkingCopyManager(
'testFileWorkingCopyType',
new TestStoredFileWorkingCopyModelFactory(),
new TestUntitledFileWorkingCopyModelFactory(),
@@ -41,12 +40,11 @@ suite('FileWorkingCopyManager', () => {
accessor.filesConfigurationService, accessor.workingCopyService, accessor.notificationService,
accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService, accessor.pathService,
accessor.environmentService, accessor.dialogService, accessor.decorationsService
);
));
});
teardown(() => {
manager.dispose();
disposables.dispose();
disposables.clear();
});
test('onDidCreate, get, workingCopies', async () => {
@@ -32,7 +32,7 @@ suite('ResourceWorkingCopy', function () {
}
let disposables: DisposableStore;
const disposables = new DisposableStore();
const resource = URI.file('test/resource');
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
@@ -43,16 +43,14 @@ suite('ResourceWorkingCopy', function () {
}
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
workingCopy = createWorkingCopy();
workingCopy = disposables.add(createWorkingCopy());
});
teardown(() => {
workingCopy.dispose();
disposables.dispose();
disposables.clear();
});
test('orphaned tracking', async () => {
@@ -129,7 +129,7 @@ suite('StoredFileWorkingCopy (with custom save)', function () {
const factory = new TestStoredFileWorkingCopyModelWithCustomSaveFactory();
let disposables: DisposableStore;
const disposables = new DisposableStore();
const resource = URI.file('test/resource');
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
@@ -142,16 +142,14 @@ suite('StoredFileWorkingCopy (with custom save)', function () {
}
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
workingCopy = createWorkingCopy();
workingCopy = disposables.add(createWorkingCopy());
});
teardown(() => {
workingCopy.dispose();
disposables.dispose();
disposables.clear();
});
test('save (custom implemented)', async () => {
@@ -200,7 +198,7 @@ suite('StoredFileWorkingCopy', function () {
const factory = new TestStoredFileWorkingCopyModelFactory();
let disposables: DisposableStore;
const disposables = new DisposableStore();
const resource = URI.file('test/resource');
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
@@ -213,16 +211,14 @@ suite('StoredFileWorkingCopy', function () {
}
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
workingCopy = createWorkingCopy();
workingCopy = disposables.add(createWorkingCopy());
});
teardown(() => {
workingCopy.dispose();
disposables.dispose();
disposables.clear();
});
test('registers with working copy service', async () => {
@@ -20,30 +20,28 @@ import { isWeb } from 'vs/base/common/platform';
suite('StoredFileWorkingCopyManager', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
let manager: IStoredFileWorkingCopyManager<TestStoredFileWorkingCopyModel>;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
manager = new StoredFileWorkingCopyManager<TestStoredFileWorkingCopyModel>(
manager = disposables.add(new StoredFileWorkingCopyManager<TestStoredFileWorkingCopyModel>(
'testStoredFileWorkingCopyType',
new TestStoredFileWorkingCopyModelFactory(),
accessor.fileService, accessor.lifecycleService, accessor.labelService, accessor.logService,
accessor.workingCopyFileService, accessor.workingCopyBackupService, accessor.uriIdentityService,
accessor.filesConfigurationService, accessor.workingCopyService, accessor.notificationService,
accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService
);
));
});
teardown(() => {
manager.dispose();
disposables.dispose();
disposables.clear();
});
test('resolve', async () => {
@@ -90,7 +90,7 @@ suite('UntitledFileWorkingCopy', () => {
const factory = new TestUntitledFileWorkingCopyModelFactory();
let disposables: DisposableStore;
const disposables = new DisposableStore();
const resource = URI.from({ scheme: Schemas.untitled, path: 'Untitled-1' });
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
@@ -113,16 +113,14 @@ suite('UntitledFileWorkingCopy', () => {
}
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
workingCopy = createWorkingCopy();
workingCopy = disposables.add(createWorkingCopy());
});
teardown(() => {
workingCopy.dispose();
disposables.dispose();
disposables.clear();
});
test('registers with working copy service', async () => {
@@ -17,21 +17,20 @@ import { TestInMemoryFileSystemProvider, TestServiceAccessor, workbenchInstantia
suite('UntitledFileWorkingCopyManager', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
let manager: IFileWorkingCopyManager<TestStoredFileWorkingCopyModel, TestUntitledFileWorkingCopyModel>;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
accessor.fileService.registerProvider(Schemas.file, new TestInMemoryFileSystemProvider());
accessor.fileService.registerProvider(Schemas.vscodeRemote, new TestInMemoryFileSystemProvider());
manager = new FileWorkingCopyManager(
manager = disposables.add(new FileWorkingCopyManager(
'testUntitledFileWorkingCopyType',
new TestStoredFileWorkingCopyModelFactory(),
new TestUntitledFileWorkingCopyModelFactory(),
@@ -40,12 +39,11 @@ suite('UntitledFileWorkingCopyManager', () => {
accessor.filesConfigurationService, accessor.workingCopyService, accessor.notificationService,
accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService, accessor.pathService,
accessor.environmentService, accessor.dialogService, accessor.decorationsService
);
));
});
teardown(() => {
manager.dispose();
disposables.dispose();
disposables.clear();
});
test('basics', async () => {
@@ -27,7 +27,7 @@ suite('UntitledScratchpadWorkingCopy', () => {
const factory = new TestUntitledFileWorkingCopyModelFactory();
let disposables: DisposableStore;
const disposables = new DisposableStore();
const resource = URI.from({ scheme: Schemas.untitled, path: 'Untitled-1' });
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
@@ -50,16 +50,14 @@ suite('UntitledScratchpadWorkingCopy', () => {
}
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
workingCopy = createWorkingCopy();
workingCopy = disposables.add(createWorkingCopy());
});
teardown(() => {
workingCopy.dispose();
disposables.dispose();
disposables.clear();
});
test('registers with working copy service', async () => {
@@ -24,13 +24,11 @@ import { TestWorkingCopy } from 'vs/workbench/test/common/workbenchTestServices'
import { CancellationToken } from 'vs/base/common/cancellation';
import { timeout } from 'vs/base/common/async';
import { BrowserWorkingCopyBackupTracker } from 'vs/workbench/services/workingCopy/browser/workingCopyBackupTracker';
import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IWorkingCopyEditorHandler, IWorkingCopyEditorService } from 'vs/workbench/services/workingCopy/common/workingCopyEditorService';
import { bufferToReadable, VSBuffer } from 'vs/base/common/buffer';
import { isWindows } from 'vs/base/common/platform';
import { Schemas } from 'vs/base/common/network';
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
import { TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
suite('WorkingCopyBackupTracker (browser)', function () {
let accessor: TestServiceAccessor;
@@ -40,7 +38,15 @@ suite('WorkingCopyBackupTracker (browser)', function () {
disposables.add(registerTestResourceEditor());
});
teardown(() => {
teardown(async () => {
for (const copy of accessor.workingCopyService.workingCopies) {
await copy.revert();
}
for (const group of accessor.editorGroupService.groups) {
await group.closeAllEditors();
}
disposables.clear();
});
@@ -85,10 +91,8 @@ suite('WorkingCopyBackupTracker (browser)', function () {
}
}
async function createTracker(): Promise<{ accessor: TestServiceAccessor; part: EditorPart; tracker: TestWorkingCopyBackupTracker; workingCopyBackupService: InMemoryTestWorkingCopyBackupService; instantiationService: IInstantiationService; cleanup: () => void }> {
const disposables = new DisposableStore();
const workingCopyBackupService = new InMemoryTestWorkingCopyBackupService();
async function createTracker(): Promise<{ accessor: TestServiceAccessor; part: EditorPart; tracker: TestWorkingCopyBackupTracker; workingCopyBackupService: InMemoryTestWorkingCopyBackupService; instantiationService: IInstantiationService }> {
const workingCopyBackupService = disposables.add(new InMemoryTestWorkingCopyBackupService());
const instantiationService = workbenchInstantiationService(undefined, disposables);
instantiationService.stub(IWorkingCopyBackupService, workingCopyBackupService);
@@ -97,20 +101,18 @@ suite('WorkingCopyBackupTracker (browser)', function () {
disposables.add(registerTestResourceEditor());
instantiationService.stub(IWorkspaceTrustRequestService, new TestWorkspaceTrustRequestService(false));
const editorService: EditorService = instantiationService.createInstance(EditorService);
const editorService: EditorService = disposables.add(instantiationService.createInstance(EditorService));
instantiationService.stub(IEditorService, editorService);
accessor = instantiationService.createInstance(TestServiceAccessor);
const tracker = disposables.add(instantiationService.createInstance(TestWorkingCopyBackupTracker));
return { accessor, part, tracker, workingCopyBackupService: workingCopyBackupService, instantiationService, cleanup: () => disposables.dispose() };
return { accessor, part, tracker, workingCopyBackupService: workingCopyBackupService, instantiationService };
}
async function untitledBackupTest(untitled: IUntitledTextResourceEditorInput = { resource: undefined }): Promise<void> {
const { accessor, cleanup, workingCopyBackupService } = await createTracker();
const { accessor, workingCopyBackupService } = await createTracker();
const untitledTextEditor = (await accessor.editorService.openEditor(untitled))?.input as UntitledTextEditorInput;
@@ -129,8 +131,6 @@ suite('WorkingCopyBackupTracker (browser)', function () {
await workingCopyBackupService.joinDiscardBackup();
assert.strictEqual(workingCopyBackupService.hasBackupSync(untitledTextModel), false);
cleanup();
}
test('Track backups (untitled)', function () {
@@ -142,14 +142,14 @@ suite('WorkingCopyBackupTracker (browser)', function () {
});
test('Track backups (custom)', async function () {
const { accessor, tracker, cleanup, workingCopyBackupService } = await createTracker();
const { accessor, tracker, workingCopyBackupService } = await createTracker();
class TestBackupWorkingCopy extends TestWorkingCopy {
constructor(resource: URI) {
super(resource);
accessor.workingCopyService.registerWorkingCopy(this);
disposables.add(accessor.workingCopyService.registerWorkingCopy(this));
}
readonly backupDelay = 10;
@@ -162,7 +162,7 @@ suite('WorkingCopyBackupTracker (browser)', function () {
}
const resource = toResource.call(this, '/path/custom.txt');
const customWorkingCopy = new TestBackupWorkingCopy(resource);
const customWorkingCopy = disposables.add(new TestBackupWorkingCopy(resource));
// Normal
customWorkingCopy.setDirty(true);
@@ -188,29 +188,22 @@ suite('WorkingCopyBackupTracker (browser)', function () {
assert.strictEqual(tracker.pendingBackupOperationCount, 1);
await workingCopyBackupService.joinDiscardBackup();
assert.strictEqual(workingCopyBackupService.hasBackupSync(customWorkingCopy), false);
customWorkingCopy.dispose();
cleanup();
});
async function restoreBackupsInit(): Promise<[TestWorkingCopyBackupTracker, TestServiceAccessor, IDisposable]> {
async function restoreBackupsInit(): Promise<[TestWorkingCopyBackupTracker, TestServiceAccessor]> {
const fooFile = URI.file(isWindows ? 'c:\\Foo' : '/Foo');
const barFile = URI.file(isWindows ? 'c:\\Bar' : '/Bar');
const untitledFile1 = URI.from({ scheme: Schemas.untitled, path: 'Untitled-1' });
const untitledFile2 = URI.from({ scheme: Schemas.untitled, path: 'Untitled-2' });
const disposables = new DisposableStore();
const workingCopyBackupService = new InMemoryTestWorkingCopyBackupService();
const workingCopyBackupService = disposables.add(new InMemoryTestWorkingCopyBackupService());
const instantiationService = workbenchInstantiationService(undefined, disposables);
instantiationService.stub(IWorkingCopyBackupService, workingCopyBackupService);
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
instantiationService.stub(IWorkspaceTrustRequestService, new TestWorkspaceTrustRequestService(false));
const editorService: EditorService = instantiationService.createInstance(EditorService);
const editorService: EditorService = disposables.add(instantiationService.createInstance(EditorService));
instantiationService.stub(IEditorService, editorService);
accessor = instantiationService.createInstance(TestServiceAccessor);
@@ -230,11 +223,11 @@ suite('WorkingCopyBackupTracker (browser)', function () {
accessor.lifecycleService.phase = LifecyclePhase.Restored;
return [tracker, accessor, disposables];
return [tracker, accessor];
}
test('Restore backups (basics, some handled)', async function () {
const [tracker, accessor, disposables] = await restoreBackupsInit();
const [tracker, accessor] = await restoreBackupsInit();
assert.strictEqual(tracker.getUnrestoredBackups().size, 0);
@@ -256,7 +249,7 @@ suite('WorkingCopyBackupTracker (browser)', function () {
createEditor: workingCopy => {
createEditorCounter++;
return accessor.instantiationService.createInstance(TestUntitledTextEditorInput, accessor.untitledTextEditorService.create({ initialValue: 'foo' }));
return disposables.add(accessor.instantiationService.createInstance(TestUntitledTextEditorInput, accessor.untitledTextEditorService.create({ initialValue: 'foo' })));
}
});
@@ -272,12 +265,10 @@ suite('WorkingCopyBackupTracker (browser)', function () {
assert.ok(editor instanceof TestUntitledTextEditorInput);
assert.strictEqual(editor.resolved, true);
}
dispose(disposables);
});
test('Restore backups (basics, none handled)', async function () {
const [tracker, accessor, disposables] = await restoreBackupsInit();
const [tracker, accessor] = await restoreBackupsInit();
await tracker.testRestoreBackups({
handles: workingCopy => false,
@@ -287,12 +278,10 @@ suite('WorkingCopyBackupTracker (browser)', function () {
assert.strictEqual(accessor.editorService.count, 0);
assert.strictEqual(tracker.getUnrestoredBackups().size, 4);
dispose(disposables);
});
test('Restore backups (basics, error case)', async function () {
const [tracker, , disposables] = await restoreBackupsInit();
const [tracker] = await restoreBackupsInit();
try {
await tracker.testRestoreBackups({
@@ -305,12 +294,10 @@ suite('WorkingCopyBackupTracker (browser)', function () {
}
assert.strictEqual(tracker.getUnrestoredBackups().size, 4);
dispose(disposables);
});
test('Restore backups (multiple handlers)', async function () {
const [tracker, accessor, disposables] = await restoreBackupsInit();
const [tracker, accessor] = await restoreBackupsInit();
const firstHandler = tracker.testRestoreBackups({
handles: workingCopy => {
@@ -346,20 +333,18 @@ suite('WorkingCopyBackupTracker (browser)', function () {
assert.ok(editor instanceof TestUntitledTextEditorInput);
assert.strictEqual(editor.resolved, true);
}
dispose(disposables);
});
test('Restore backups (editors already opened)', async function () {
const [tracker, accessor, disposables] = await restoreBackupsInit();
const [tracker, accessor] = await restoreBackupsInit();
assert.strictEqual(tracker.getUnrestoredBackups().size, 0);
let handlesCounter = 0;
let isOpenCounter = 0;
const editor1 = accessor.instantiationService.createInstance(TestUntitledTextEditorInput, accessor.untitledTextEditorService.create({ initialValue: 'foo' }));
const editor2 = accessor.instantiationService.createInstance(TestUntitledTextEditorInput, accessor.untitledTextEditorService.create({ initialValue: 'foo' }));
const editor1 = disposables.add(accessor.instantiationService.createInstance(TestUntitledTextEditorInput, accessor.untitledTextEditorService.create({ initialValue: 'foo' })));
const editor2 = disposables.add(accessor.instantiationService.createInstance(TestUntitledTextEditorInput, accessor.untitledTextEditorService.create({ initialValue: 'foo' })));
await accessor.editorService.openEditors([{ editor: editor1 }, { editor: editor2 }]);
@@ -396,7 +381,5 @@ suite('WorkingCopyBackupTracker (browser)', function () {
assert.strictEqual(editor.resolved, true);
}
}
dispose(disposables);
});
});
@@ -6,12 +6,11 @@
import * as assert from 'assert';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
import { IWorkingCopyEditorHandler, WorkingCopyEditorService } from 'vs/workbench/services/workingCopy/common/workingCopyEditorService';
import { TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { createEditorPart, registerTestResourceEditor, TestEditorService, TestServiceAccessor, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestWorkingCopy } from 'vs/workbench/test/common/workbenchTestServices';
@@ -28,12 +27,12 @@ suite('WorkingCopyEditorService', () => {
});
test('registry - basics', () => {
const service = new WorkingCopyEditorService(new TestEditorService());
const service = disposables.add(new WorkingCopyEditorService(new TestEditorService()));
let handlerEvent: IWorkingCopyEditorHandler | undefined = undefined;
service.onDidRegisterHandler(handler => {
disposables.add(service.onDidRegisterHandler(handler => {
handlerEvent = handler;
});
}));
const editorHandler: IWorkingCopyEditorHandler = {
handles: workingCopy => false,
@@ -41,11 +40,9 @@ suite('WorkingCopyEditorService', () => {
createEditor: workingCopy => { throw new Error(); }
};
const disposable = service.registerHandler(editorHandler);
disposables.add(service.registerHandler(editorHandler));
assert.strictEqual(handlerEvent, editorHandler);
disposable.dispose();
});
test('findEditor', async () => {
@@ -55,14 +52,13 @@ suite('WorkingCopyEditorService', () => {
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
instantiationService.stub(IWorkspaceTrustRequestService, new TestWorkspaceTrustRequestService(false));
const editorService = instantiationService.createInstance(EditorService);
const editorService = disposables.add(instantiationService.createInstance(EditorService));
const accessor = instantiationService.createInstance(TestServiceAccessor);
const service = new WorkingCopyEditorService(editorService);
const service = disposables.add(new WorkingCopyEditorService(editorService));
const resource = URI.parse('custom://some/folder/custom.txt');
const testWorkingCopy = new TestWorkingCopy(resource, false, 'testWorkingCopyTypeId1');
const testWorkingCopy = disposables.add(new TestWorkingCopy(resource, false, 'testWorkingCopyTypeId1'));
assert.strictEqual(service.findEditor(testWorkingCopy), undefined);
@@ -74,8 +70,8 @@ suite('WorkingCopyEditorService', () => {
disposables.add(service.registerHandler(editorHandler));
const editor1 = instantiationService.createInstance(UntitledTextEditorInput, accessor.untitledTextEditorService.create({ initialValue: 'foo' }));
const editor2 = instantiationService.createInstance(UntitledTextEditorInput, accessor.untitledTextEditorService.create({ initialValue: 'foo' }));
const editor1 = disposables.add(instantiationService.createInstance(UntitledTextEditorInput, accessor.untitledTextEditorService.create({ initialValue: 'foo' })));
const editor2 = disposables.add(instantiationService.createInstance(UntitledTextEditorInput, accessor.untitledTextEditorService.create({ initialValue: 'foo' })));
await editorService.openEditors([{ editor: editor1 }, { editor: editor2 }]);
@@ -83,4 +79,6 @@ suite('WorkingCopyEditorService', () => {
disposables.dispose();
});
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -20,19 +20,18 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
suite('WorkingCopyFileService', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
disposables.add(<TextFileEditorModelManager>accessor.textFileService.files);
});
teardown(() => {
(<TextFileEditorModelManager>accessor.textFileService.files).dispose();
disposables.dispose();
disposables.clear();
});
test('create - dirty file', async function () {
@@ -30,6 +30,8 @@ import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFil
import { generateUuid } from 'vs/base/common/uuid';
import { INativeWindowConfiguration } from 'vs/platform/window/common/window';
import product from 'vs/platform/product/common/product';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { DisposableStore } from 'vs/base/common/lifecycle';
const homeDir = URI.file('home').with({ scheme: Schemas.inMemory });
const tmpDir = URI.file('tmp').with({ scheme: Schemas.inMemory });
@@ -170,6 +172,8 @@ suite('WorkingCopyBackupService', () => {
let service: NodeTestWorkingCopyBackupService;
let fileService: IFileService;
const disposables = new DisposableStore();
const workspaceResource = URI.file(isWindows ? 'c:\\workspace' : '/workspace');
const fooFile = URI.file(isWindows ? 'c:\\Foo' : '/Foo');
const customFile = URI.parse('customScheme://some/path');
@@ -184,7 +188,7 @@ suite('WorkingCopyBackupService', () => {
workspacesJsonPath = joinPath(backupHome, 'workspaces.json');
workspaceBackupPath = joinPath(backupHome, hash(workspaceResource.fsPath).toString(16));
service = new NodeTestWorkingCopyBackupService(testDir, workspaceBackupPath);
service = disposables.add(new NodeTestWorkingCopyBackupService(testDir, workspaceBackupPath));
fileService = service._fileService;
await fileService.createFolder(backupHome);
@@ -192,6 +196,10 @@ suite('WorkingCopyBackupService', () => {
return fileService.writeFile(workspacesJsonPath, VSBuffer.fromString(''));
});
teardown(() => {
disposables.clear();
});
suite('hashIdentifier', () => {
test('should correctly hash the identifier for untitled scheme URIs', () => {
const uri = URI.from({ scheme: Schemas.untitled, path: 'Untitled-1' });
@@ -1296,4 +1304,6 @@ suite('WorkingCopyBackupService', () => {
assert.ok(backups.every(backup => backup.typeId === ''));
});
});
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -16,7 +16,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { toResource } from 'vs/base/test/common/utils';
import { ensureNoDisposablesAreLeakedInTestSuite, toResource } from 'vs/base/test/common/utils';
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { ILogService } from 'vs/platform/log/common/log';
@@ -28,7 +28,7 @@ import { INativeHostService } from 'vs/platform/native/common/native';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { createEditorPart, registerTestFileEditor, TestBeforeShutdownEvent, TestEnvironmentService, TestFilesConfigurationService, TestFileService } from 'vs/workbench/test/browser/workbenchTestServices';
import { createEditorPart, registerTestFileEditor, TestBeforeShutdownEvent, TestEnvironmentService, TestFilesConfigurationService, TestFileService, workbenchTeardown } from 'vs/workbench/test/browser/workbenchTestServices';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@@ -82,8 +82,9 @@ suite('WorkingCopyBackupTracker (native)', function () {
override dispose() {
super.dispose();
for (const [_, disposable] of this.pendingBackupOperations) {
disposable.dispose();
for (const [_, pending] of this.pendingBackupOperations) {
pending.cancel();
pending.disposable.dispose();
}
}
@@ -113,11 +114,10 @@ suite('WorkingCopyBackupTracker (native)', function () {
let workspaceBackupPath: URI;
let accessor: TestServiceAccessor;
let disposables: DisposableStore;
const disposables = new DisposableStore();
setup(async () => {
disposables = new DisposableStore();
testDir = URI.file(join(generateUuid(), 'vsctests', 'workingcopybackuptracker')).with({ scheme: Schemas.inMemory });
backupHome = joinPath(testDir, 'Backups');
const workspacesJsonPath = joinPath(backupHome, 'workspaces.json');
@@ -137,8 +137,8 @@ suite('WorkingCopyBackupTracker (native)', function () {
return accessor.fileService.writeFile(workspacesJsonPath, VSBuffer.fromString(''));
});
teardown(async () => {
disposables.dispose();
teardown(() => {
disposables.clear();
});
async function createTracker(autoSaveEnabled = false): Promise<{ accessor: TestServiceAccessor; part: EditorPart; tracker: TestWorkingCopyBackupTracker; instantiationService: IInstantiationService; cleanup: () => Promise<void> }> {
@@ -150,19 +150,19 @@ suite('WorkingCopyBackupTracker (native)', function () {
}
instantiationService.stub(IConfigurationService, configurationService);
instantiationService.stub(IFilesConfigurationService, new TestFilesConfigurationService(
instantiationService.stub(IFilesConfigurationService, disposables.add(new TestFilesConfigurationService(
<IContextKeyService>instantiationService.createInstance(MockContextKeyService),
configurationService,
new TestContextService(TestWorkspace),
TestEnvironmentService,
new UriIdentityService(new TestFileService()),
new TestFileService()
));
disposables.add(new UriIdentityService(disposables.add(new TestFileService()))),
disposables.add(new TestFileService())
)));
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
const editorService: EditorService = instantiationService.createInstance(EditorService);
const editorService: EditorService = disposables.add(instantiationService.createInstance(EditorService));
instantiationService.stub(IEditorService, editorService);
accessor = instantiationService.createInstance(TestServiceAccessor);
@@ -170,8 +170,9 @@ suite('WorkingCopyBackupTracker (native)', function () {
const tracker = instantiationService.createInstance(TestWorkingCopyBackupTracker);
const cleanup = async () => {
// File changes could also schedule some backup operations so we need to wait for them before finishing the test
await accessor.workingCopyBackupService.waitForAllBackups();
await accessor.workingCopyBackupService.waitForAllBackups(); // File changes could also schedule some backup operations so we need to wait for them before finishing the test
await workbenchTeardown(instantiationService);
part.dispose();
tracker.dispose();
@@ -356,7 +357,7 @@ suite('WorkingCopyBackupTracker (native)', function () {
constructor(resource: URI) {
super(resource);
accessor.workingCopyService.registerWorkingCopy(this);
this._register(accessor.workingCopyService.registerWorkingCopy(this));
}
override async backup(token: CancellationToken): Promise<IWorkingCopyBackup> {
@@ -365,7 +366,7 @@ suite('WorkingCopyBackupTracker (native)', function () {
}
const resource = toResource.call(this, '/path/custom.txt');
const customWorkingCopy = new TestBackupWorkingCopy(resource);
const customWorkingCopy = disposables.add(new TestBackupWorkingCopy(resource));
customWorkingCopy.setDirty(true);
const event = new TestBeforeShutdownEvent();
@@ -389,7 +390,7 @@ suite('WorkingCopyBackupTracker (native)', function () {
constructor(resource: URI) {
super(resource);
accessor.workingCopyService.registerWorkingCopy(this);
this._register(accessor.workingCopyService.registerWorkingCopy(this));
}
override capabilities = WorkingCopyCapabilities.Untitled | WorkingCopyCapabilities.Scratchpad;
@@ -408,7 +409,7 @@ suite('WorkingCopyBackupTracker (native)', function () {
}
const resource = toResource.call(this, '/path/custom.txt');
new TestBackupWorkingCopy(resource);
disposables.add(new TestBackupWorkingCopy(resource));
const event = new TestBeforeShutdownEvent();
event.reason = ShutdownReason.QUIT;
@@ -716,7 +717,7 @@ suite('WorkingCopyBackupTracker (native)', function () {
constructor(resource: URI) {
super(resource);
accessor.workingCopyService.registerWorkingCopy(this);
this._register(accessor.workingCopyService.registerWorkingCopy(this));
}
override capabilities = WorkingCopyCapabilities.Untitled | WorkingCopyCapabilities.Scratchpad;
@@ -747,7 +748,7 @@ suite('WorkingCopyBackupTracker (native)', function () {
accessor.fileDialogService.setConfirmResult(ConfirmResult.CANCEL);
const resource = toResource.call(this, '/path/custom.txt');
new TestBackupWorkingCopy(resource);
disposables.add(new TestBackupWorkingCopy(resource));
const event = new TestBeforeShutdownEvent();
event.reason = shutdownReason;
@@ -761,4 +762,6 @@ suite('WorkingCopyBackupTracker (native)', function () {
await cleanup();
}
});
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -23,6 +23,8 @@ import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFil
import { generateUuid } from 'vs/base/common/uuid';
import { join } from 'vs/base/common/path';
import { VSBuffer } from 'vs/base/common/buffer';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { DisposableStore } from 'vs/base/common/lifecycle';
export class TestWorkingCopyHistoryService extends NativeWorkingCopyHistoryService {
@@ -30,24 +32,20 @@ export class TestWorkingCopyHistoryService extends NativeWorkingCopyHistoryServi
readonly _configurationService: TestConfigurationService;
readonly _lifecycleService: TestLifecycleService;
constructor(fileService?: IFileService) {
constructor(disposables: DisposableStore, fileService?: IFileService) {
const environmentService = TestEnvironmentService;
const logService = new NullLogService();
if (!fileService) {
fileService = new FileService(logService);
fileService.registerProvider(Schemas.inMemory, new InMemoryFileSystemProvider());
fileService.registerProvider(Schemas.vscodeUserData, new InMemoryFileSystemProvider());
fileService = disposables.add(new FileService(logService));
disposables.add(fileService.registerProvider(Schemas.inMemory, disposables.add(new InMemoryFileSystemProvider())));
disposables.add(fileService.registerProvider(Schemas.vscodeUserData, disposables.add(new InMemoryFileSystemProvider())));
}
const remoteAgentService = new TestRemoteAgentService();
const uriIdentityService = new UriIdentityService(fileService);
const labelService = new LabelService(environmentService, new TestContextService(), new TestPathService(), new TestRemoteAgentService(), new TestStorageService(), new TestLifecycleService());
const lifecycleService = new TestLifecycleService();
const uriIdentityService = disposables.add(new UriIdentityService(fileService));
const lifecycleService = disposables.add(new TestLifecycleService());
const labelService = disposables.add(new LabelService(environmentService, new TestContextService(), new TestPathService(), new TestRemoteAgentService(), disposables.add(new TestStorageService()), lifecycleService));
const configurationService = new TestConfigurationService();
super(fileService, remoteAgentService, environmentService, uriIdentityService, labelService, lifecycleService, logService, configurationService);
@@ -60,6 +58,8 @@ export class TestWorkingCopyHistoryService extends NativeWorkingCopyHistoryServi
suite('WorkingCopyHistoryService', () => {
const disposables = new DisposableStore();
let testDir: URI;
let historyHome: URI;
let workHome: URI;
@@ -84,7 +84,7 @@ suite('WorkingCopyHistoryService', () => {
historyHome = joinPath(testDir, 'User', 'History');
workHome = joinPath(testDir, 'work');
service = new TestWorkingCopyHistoryService();
service = disposables.add(new TestWorkingCopyHistoryService(disposables));
fileService = service._fileService;
await fileService.createFolder(historyHome);
@@ -118,15 +118,15 @@ suite('WorkingCopyHistoryService', () => {
}
teardown(() => {
service.dispose();
disposables.clear();
});
test('addEntry', async () => {
const addEvents: IWorkingCopyHistoryEvent[] = [];
service.onDidAddEntry(e => addEvents.push(e));
disposables.add(service.onDidAddEntry(e => addEvents.push(e)));
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy2 = new TestWorkingCopy(testFile2Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const workingCopy2 = disposables.add(new TestWorkingCopy(testFile2Path));
// Add Entry works
@@ -164,7 +164,7 @@ suite('WorkingCopyHistoryService', () => {
// Invalid working copies are ignored
const workingCopy3 = new TestWorkingCopy(testFile2Path.with({ scheme: 'unsupported' }));
const workingCopy3 = disposables.add(new TestWorkingCopy(testFile2Path.with({ scheme: 'unsupported' })));
const entry3A = await addEntry({ resource: workingCopy3.resource }, CancellationToken.None, false);
assert.ok(!entry3A);
@@ -173,9 +173,9 @@ suite('WorkingCopyHistoryService', () => {
test('renameEntry', async () => {
const changeEvents: IWorkingCopyHistoryEvent[] = [];
service.onDidChangeEntry(e => changeEvents.push(e));
disposables.add(service.onDidChangeEntry(e => changeEvents.push(e)));
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const entry = await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
@@ -200,7 +200,7 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
entries = await service.getEntries(workingCopy1.resource, CancellationToken.None);
assert.strictEqual(entries.length, 3);
@@ -209,9 +209,9 @@ suite('WorkingCopyHistoryService', () => {
test('removeEntry', async () => {
const removeEvents: IWorkingCopyHistoryEvent[] = [];
service.onDidRemoveEntry(e => removeEvents.push(e));
disposables.add(service.onDidRemoveEntry(e => removeEvents.push(e)));
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
const entry2 = await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
@@ -242,14 +242,14 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
entries = await service.getEntries(workingCopy1.resource, CancellationToken.None);
assert.strictEqual(entries.length, 3);
});
test('removeEntry - deletes history entries folder when last entry removed', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
let entry = await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
@@ -261,7 +261,7 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
assert.strictEqual((await fileService.exists(dirname(entry.location))), true);
@@ -278,17 +278,17 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
assert.strictEqual((await fileService.exists(dirname(entry.location))), false);
});
test('removeAll', async () => {
let removed = false;
service.onDidRemoveEntries(() => removed = true);
disposables.add(service.onDidRemoveEntries(() => removed = true));
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy2 = new TestWorkingCopy(testFile2Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const workingCopy2 = disposables.add(new TestWorkingCopy(testFile2Path));
await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
@@ -317,7 +317,7 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
entries = await service.getEntries(workingCopy1.resource, CancellationToken.None);
assert.strictEqual(entries.length, 0);
@@ -326,8 +326,8 @@ suite('WorkingCopyHistoryService', () => {
});
test('getEntries - simple', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy2 = new TestWorkingCopy(testFile2Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const workingCopy2 = disposables.add(new TestWorkingCopy(testFile2Path));
let entries = await service.getEntries(workingCopy1.resource, CancellationToken.None);
assert.strictEqual(entries.length, 0);
@@ -355,8 +355,8 @@ suite('WorkingCopyHistoryService', () => {
});
test('getEntries - metadata preserved when stored', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy2 = new TestWorkingCopy(testFile2Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const workingCopy2 = disposables.add(new TestWorkingCopy(testFile2Path));
const entry1 = await addEntry({ resource: workingCopy1.resource, source: 'test-source' }, CancellationToken.None);
const entry2 = await addEntry({ resource: workingCopy2.resource }, CancellationToken.None);
@@ -370,7 +370,7 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
let entries = await service.getEntries(workingCopy1.resource, CancellationToken.None);
assert.strictEqual(entries.length, 1);
@@ -383,7 +383,7 @@ suite('WorkingCopyHistoryService', () => {
});
test('getEntries - corrupt meta.json is no problem', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const entry1 = await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
@@ -395,7 +395,7 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
const metaFile = joinPath(dirname(entry1.location), 'entries.json');
assert.ok((await fileService.exists(metaFile)));
@@ -407,7 +407,7 @@ suite('WorkingCopyHistoryService', () => {
});
test('getEntries - missing entries from meta.json is no problem', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const entry1 = await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
const entry2 = await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
@@ -420,7 +420,7 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
await fileService.del(entry1.location);
@@ -430,7 +430,7 @@ suite('WorkingCopyHistoryService', () => {
});
test('getEntries - in-memory and on-disk entries are merged', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const entry1 = await addEntry({ resource: workingCopy1.resource, source: 'test-source' }, CancellationToken.None);
const entry2 = await addEntry({ resource: workingCopy1.resource, source: 'other-source' }, CancellationToken.None);
@@ -443,7 +443,7 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
const entry3 = await addEntry({ resource: workingCopy1.resource, source: 'test-source' }, CancellationToken.None);
const entry4 = await addEntry({ resource: workingCopy1.resource, source: 'other-source' }, CancellationToken.None);
@@ -457,7 +457,7 @@ suite('WorkingCopyHistoryService', () => {
});
test('getEntries - configured max entries respected', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
await addEntry({ resource: workingCopy1.resource }, CancellationToken.None);
@@ -483,8 +483,8 @@ suite('WorkingCopyHistoryService', () => {
});
test('getAll', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy2 = new TestWorkingCopy(testFile2Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const workingCopy2 = disposables.add(new TestWorkingCopy(testFile2Path));
let resources = await service.getAll(CancellationToken.None);
assert.strictEqual(resources.length, 0);
@@ -510,9 +510,9 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
const workingCopy3 = new TestWorkingCopy(testFile3Path);
const workingCopy3 = disposables.add(new TestWorkingCopy(testFile3Path));
await addEntry({ resource: workingCopy3.resource, source: 'test-source' }, CancellationToken.None);
resources = await service.getAll(CancellationToken.None);
@@ -525,7 +525,7 @@ suite('WorkingCopyHistoryService', () => {
});
test('getAll - ignores resource when no entries exist', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const entry = await addEntry({ resource: workingCopy1.resource, source: 'test-source' }, CancellationToken.None);
@@ -545,7 +545,7 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
resources = await service.getAll(CancellationToken.None);
assert.strictEqual(resources.length, 0);
@@ -563,7 +563,7 @@ suite('WorkingCopyHistoryService', () => {
}
test('entries cleaned up on shutdown', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const entry1 = await addEntry({ resource: workingCopy1.resource, source: 'test-source' }, CancellationToken.None);
const entry2 = await addEntry({ resource: workingCopy1.resource, source: 'other-source' }, CancellationToken.None);
@@ -585,7 +585,7 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
let entries = await service.getEntries(workingCopy1.resource, CancellationToken.None);
assert.strictEqual(entries.length, 2);
@@ -608,7 +608,7 @@ suite('WorkingCopyHistoryService', () => {
// Resolve from file service fresh and verify again
service.dispose();
service = new TestWorkingCopyHistoryService(fileService);
service = disposables.add(new TestWorkingCopyHistoryService(disposables, fileService));
entries = await service.getEntries(workingCopy1.resource, CancellationToken.None);
assert.strictEqual(entries.length, 3);
@@ -619,9 +619,9 @@ suite('WorkingCopyHistoryService', () => {
test('entries are merged when source is same', async () => {
let replaced: IWorkingCopyHistoryEntry | undefined = undefined;
service.onDidReplaceEntry(e => replaced = e.entry);
disposables.add(service.onDidReplaceEntry(e => replaced = e.entry));
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
service._configurationService.setUserConfiguration('workbench.localHistory.mergeWindow', 1);
@@ -648,7 +648,7 @@ suite('WorkingCopyHistoryService', () => {
});
test('move entries (file rename)', async () => {
const workingCopy = new TestWorkingCopy(testFile1Path);
const workingCopy = disposables.add(new TestWorkingCopy(testFile1Path));
const entry1 = await addEntry({ resource: workingCopy.resource, source: 'test-source' }, CancellationToken.None);
const entry2 = await addEntry({ resource: workingCopy.resource, source: 'test-source' }, CancellationToken.None);
@@ -695,8 +695,8 @@ suite('WorkingCopyHistoryService', () => {
});
test('entries moved (folder rename)', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy2 = new TestWorkingCopy(testFile2Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const workingCopy2 = disposables.add(new TestWorkingCopy(testFile2Path));
const entry1A = await addEntry({ resource: workingCopy1.resource, source: 'test-source' }, CancellationToken.None);
const entry2A = await addEntry({ resource: workingCopy1.resource, source: 'test-source' }, CancellationToken.None);
@@ -782,4 +782,6 @@ suite('WorkingCopyHistoryService', () => {
}
}
});
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -5,14 +5,14 @@
import * as assert from 'assert';
import { Event } from 'vs/base/common/event';
import { TestContextService, TestStorageService, TestWorkingCopy } from 'vs/workbench/test/common/workbenchTestServices';
import { TestContextService, TestWorkingCopy } from 'vs/workbench/test/common/workbenchTestServices';
import { randomPath } from 'vs/base/common/extpath';
import { join } from 'vs/base/common/path';
import { URI } from 'vs/base/common/uri';
import { WorkingCopyHistoryTracker } from 'vs/workbench/services/workingCopy/common/workingCopyHistoryTracker';
import { WorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService';
import { TestEnvironmentService, TestFileService, TestLifecycleService, TestPathService, TestRemoteAgentService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestFileService, TestPathService } from 'vs/workbench/test/browser/workbenchTestServices';
import { DeferredPromise } from 'vs/base/common/async';
import { IFileService } from 'vs/platform/files/common/files';
import { Schemas } from 'vs/base/common/network';
@@ -25,43 +25,9 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { IWorkingCopyHistoryEntry, IWorkingCopyHistoryEntryDescriptor } from 'vs/workbench/services/workingCopy/common/workingCopyHistory';
import { assertIsDefined } from 'vs/base/common/types';
import { VSBuffer } from 'vs/base/common/buffer';
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
import { IDisposable } from 'vs/base/common/lifecycle';
import { NativeWorkingCopyHistoryService } from 'vs/workbench/services/workingCopy/common/workingCopyHistoryService';
import { NullLogService } from 'vs/platform/log/common/log';
import { FileService } from 'vs/platform/files/common/fileService';
import { LabelService } from 'vs/workbench/services/label/common/labelService';
class TestWorkingCopyHistoryService extends NativeWorkingCopyHistoryService {
readonly _fileService: IFileService;
readonly _configurationService: TestConfigurationService;
readonly _lifecycleService: TestLifecycleService;
constructor(testDir: URI | string) {
const environmentService = TestEnvironmentService;
const logService = new NullLogService();
const fileService = new FileService(logService);
fileService.registerProvider(Schemas.vscodeUserData, new InMemoryFileSystemProvider());
const remoteAgentService = new TestRemoteAgentService();
const uriIdentityService = new UriIdentityService(fileService);
const labelService = new LabelService(environmentService, new TestContextService(), new TestPathService(), new TestRemoteAgentService(), new TestStorageService(), new TestLifecycleService());
const lifecycleService = new TestLifecycleService();
const configurationService = new TestConfigurationService();
super(fileService, remoteAgentService, environmentService, uriIdentityService, labelService, lifecycleService, logService, configurationService);
this._fileService = fileService;
this._configurationService = configurationService;
this._lifecycleService = lifecycleService;
}
}
import { DisposableStore } from 'vs/base/common/lifecycle';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { TestWorkingCopyHistoryService } from 'vs/workbench/services/workingCopy/test/electron-sandbox/workingCopyHistoryService.test';
suite('WorkingCopyHistoryTracker', () => {
@@ -73,13 +39,14 @@ suite('WorkingCopyHistoryTracker', () => {
let workingCopyService: WorkingCopyService;
let fileService: IFileService;
let configurationService: TestConfigurationService;
let inMemoryFileSystemDisposable: IDisposable;
let tracker: WorkingCopyHistoryTracker;
let testFile1Path: URI;
let testFile2Path: URI;
const disposables = new DisposableStore();
const testFile1PathContents = 'Hello Foo';
const testFile2PathContents = [
'Lorem ipsum ',
@@ -104,14 +71,12 @@ suite('WorkingCopyHistoryTracker', () => {
historyHome = joinPath(testDir, 'User', 'History');
workHome = joinPath(testDir, 'work');
workingCopyHistoryService = new TestWorkingCopyHistoryService(testDir);
workingCopyService = new WorkingCopyService();
workingCopyHistoryService = disposables.add(new TestWorkingCopyHistoryService(disposables));
workingCopyService = disposables.add(new WorkingCopyService());
fileService = workingCopyHistoryService._fileService;
configurationService = workingCopyHistoryService._configurationService;
inMemoryFileSystemDisposable = fileService.registerProvider(Schemas.inMemory, new InMemoryFileSystemProvider());
tracker = createTracker();
tracker = disposables.add(createTracker());
await fileService.createFolder(historyHome);
await fileService.createFolder(workHome);
@@ -127,7 +92,7 @@ suite('WorkingCopyHistoryTracker', () => {
return new WorkingCopyHistoryTracker(
workingCopyService,
workingCopyHistoryService,
new UriIdentityService(new TestFileService()),
disposables.add(new UriIdentityService(disposables.add(new TestFileService()))),
new TestPathService(undefined, Schemas.file),
configurationService,
new UndoRedoService(new TestDialogService(), new TestNotificationService()),
@@ -137,28 +102,23 @@ suite('WorkingCopyHistoryTracker', () => {
}
teardown(async () => {
workingCopyHistoryService.dispose();
workingCopyService.dispose();
tracker.dispose();
await fileService.del(testDir, { recursive: true });
inMemoryFileSystemDisposable.dispose();
disposables.clear();
});
test('history entry added on save', async () => {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy2 = new TestWorkingCopy(testFile2Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const workingCopy2 = disposables.add(new TestWorkingCopy(testFile2Path));
const stat1 = await fileService.resolve(workingCopy1.resource, { resolveMetadata: true });
const stat2 = await fileService.resolve(workingCopy2.resource, { resolveMetadata: true });
workingCopyService.registerWorkingCopy(workingCopy1);
workingCopyService.registerWorkingCopy(workingCopy2);
disposables.add(workingCopyService.registerWorkingCopy(workingCopy1));
disposables.add(workingCopyService.registerWorkingCopy(workingCopy2));
const saveResult = new DeferredPromise<void>();
let addedCounter = 0;
workingCopyHistoryService.onDidAddEntry(e => {
disposables.add(workingCopyHistoryService.onDidAddEntry(e => {
if (isEqual(e.entry.workingCopy.resource, workingCopy1.resource) || isEqual(e.entry.workingCopy.resource, workingCopy2.resource)) {
addedCounter++;
@@ -166,7 +126,7 @@ suite('WorkingCopyHistoryTracker', () => {
saveResult.complete();
}
}
});
}));
await workingCopy1.save(undefined, stat1);
await workingCopy2.save(undefined, stat2);
@@ -185,7 +145,7 @@ suite('WorkingCopyHistoryTracker', () => {
// Recreate to apply settings
tracker.dispose();
tracker = createTracker();
tracker = disposables.add(createTracker());
return assertNoLocalHistoryEntryAddedWithSettingsConfigured();
});
@@ -197,17 +157,17 @@ suite('WorkingCopyHistoryTracker', () => {
});
async function assertNoLocalHistoryEntryAddedWithSettingsConfigured(): Promise<void> {
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy2 = new TestWorkingCopy(testFile2Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const workingCopy2 = disposables.add(new TestWorkingCopy(testFile2Path));
const stat1 = await fileService.resolve(workingCopy1.resource, { resolveMetadata: true });
const stat2 = await fileService.resolve(workingCopy2.resource, { resolveMetadata: true });
workingCopyService.registerWorkingCopy(workingCopy1);
workingCopyService.registerWorkingCopy(workingCopy2);
disposables.add(workingCopyService.registerWorkingCopy(workingCopy1));
disposables.add(workingCopyService.registerWorkingCopy(workingCopy2));
const saveResult = new DeferredPromise<void>();
workingCopyHistoryService.onDidAddEntry(e => {
disposables.add(workingCopyHistoryService.onDidAddEntry(e => {
if (isEqual(e.entry.workingCopy.resource, workingCopy1.resource)) {
assert.fail('Unexpected working copy history entry: ' + e.entry.workingCopy.resource.toString());
}
@@ -215,7 +175,7 @@ suite('WorkingCopyHistoryTracker', () => {
if (isEqual(e.entry.workingCopy.resource, workingCopy2.resource)) {
saveResult.complete();
}
});
}));
await workingCopy1.save(undefined, stat1);
await workingCopy2.save(undefined, stat2);
@@ -226,7 +186,7 @@ suite('WorkingCopyHistoryTracker', () => {
test('entries moved (file rename)', async () => {
const entriesMoved = Event.toPromise(workingCopyHistoryService.onDidMoveEntries);
const workingCopy = new TestWorkingCopy(testFile1Path);
const workingCopy = disposables.add(new TestWorkingCopy(testFile1Path));
const entry1 = await addEntry({ resource: workingCopy.resource, source: 'test-source' }, CancellationToken.None);
const entry2 = await addEntry({ resource: workingCopy.resource, source: 'test-source' }, CancellationToken.None);
@@ -272,8 +232,8 @@ suite('WorkingCopyHistoryTracker', () => {
test('entries moved (folder rename)', async () => {
const entriesMoved = Event.toPromise(workingCopyHistoryService.onDidMoveEntries);
const workingCopy1 = new TestWorkingCopy(testFile1Path);
const workingCopy2 = new TestWorkingCopy(testFile2Path);
const workingCopy1 = disposables.add(new TestWorkingCopy(testFile1Path));
const workingCopy2 = disposables.add(new TestWorkingCopy(testFile2Path));
const entry1A = await addEntry({ resource: workingCopy1.resource, source: 'test-source' }, CancellationToken.None);
const entry2A = await addEntry({ resource: workingCopy1.resource, source: 'test-source' }, CancellationToken.None);
@@ -352,5 +312,6 @@ suite('WorkingCopyHistoryTracker', () => {
}
}
});
});
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -1,144 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { IWorkspaceTrustEnablementService, IWorkspaceTrustManagementService, IWorkspaceTrustRequestService, IWorkspaceTrustTransitionParticipant, IWorkspaceTrustUriInfo, WorkspaceTrustRequestOptions, WorkspaceTrustUriResponse } from 'vs/platform/workspace/common/workspaceTrust';
export class TestWorkspaceTrustEnablementService implements IWorkspaceTrustEnablementService {
_serviceBrand: undefined;
constructor(private isEnabled: boolean = true) { }
isWorkspaceTrustEnabled(): boolean {
return this.isEnabled;
}
}
export class TestWorkspaceTrustManagementService implements IWorkspaceTrustManagementService {
_serviceBrand: undefined;
private _onDidChangeTrust = new Emitter<boolean>();
onDidChangeTrust = this._onDidChangeTrust.event;
private _onDidChangeTrustedFolders = new Emitter<void>();
onDidChangeTrustedFolders = this._onDidChangeTrustedFolders.event;
private _onDidInitiateWorkspaceTrustRequestOnStartup = new Emitter<void>();
onDidInitiateWorkspaceTrustRequestOnStartup = this._onDidInitiateWorkspaceTrustRequestOnStartup.event;
constructor(
private trusted: boolean = true
) { }
get acceptsOutOfWorkspaceFiles(): boolean {
throw new Error('Method not implemented.');
}
set acceptsOutOfWorkspaceFiles(value: boolean) {
throw new Error('Method not implemented.');
}
addWorkspaceTrustTransitionParticipant(participant: IWorkspaceTrustTransitionParticipant): IDisposable {
throw new Error('Method not implemented.');
}
getTrustedUris(): URI[] {
throw new Error('Method not implemented.');
}
setParentFolderTrust(trusted: boolean): Promise<void> {
throw new Error('Method not implemented.');
}
getUriTrustInfo(uri: URI): Promise<IWorkspaceTrustUriInfo> {
throw new Error('Method not implemented.');
}
async setTrustedUris(folders: URI[]): Promise<void> {
throw new Error('Method not implemented.');
}
async setUrisTrust(uris: URI[], trusted: boolean): Promise<void> {
throw new Error('Method not implemented.');
}
canSetParentFolderTrust(): boolean {
throw new Error('Method not implemented.');
}
canSetWorkspaceTrust(): boolean {
throw new Error('Method not implemented.');
}
isWorkspaceTrusted(): boolean {
return this.trusted;
}
isWorkspaceTrustForced(): boolean {
return false;
}
get workspaceTrustInitialized(): Promise<void> {
return Promise.resolve();
}
get workspaceResolved(): Promise<void> {
return Promise.resolve();
}
async setWorkspaceTrust(trusted: boolean): Promise<void> {
if (this.trusted !== trusted) {
this.trusted = trusted;
this._onDidChangeTrust.fire(this.trusted);
}
}
}
export class TestWorkspaceTrustRequestService implements IWorkspaceTrustRequestService {
_serviceBrand: any;
private readonly _onDidInitiateOpenFilesTrustRequest = new Emitter<void>();
readonly onDidInitiateOpenFilesTrustRequest = this._onDidInitiateOpenFilesTrustRequest.event;
private readonly _onDidInitiateWorkspaceTrustRequest = new Emitter<WorkspaceTrustRequestOptions>();
readonly onDidInitiateWorkspaceTrustRequest = this._onDidInitiateWorkspaceTrustRequest.event;
private readonly _onDidInitiateWorkspaceTrustRequestOnStartup = new Emitter<void>();
readonly onDidInitiateWorkspaceTrustRequestOnStartup = this._onDidInitiateWorkspaceTrustRequestOnStartup.event;
constructor(private readonly _trusted: boolean) { }
requestOpenUrisHandler = async (uris: URI[]) => {
return WorkspaceTrustUriResponse.Open;
};
requestOpenFilesTrust(uris: URI[]): Promise<WorkspaceTrustUriResponse> {
return this.requestOpenUrisHandler(uris);
}
async completeOpenFilesTrustRequest(result: WorkspaceTrustUriResponse, saveResponse: boolean): Promise<void> {
throw new Error('Method not implemented.');
}
cancelWorkspaceTrustRequest(): void {
throw new Error('Method not implemented.');
}
async completeWorkspaceTrustRequest(trusted?: boolean): Promise<void> {
throw new Error('Method not implemented.');
}
async requestWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Promise<boolean> {
return this._trusted;
}
requestWorkspaceTrustOnStartup(): void {
throw new Error('Method not implemented.');
}
}
@@ -21,8 +21,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { UriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentityService';
import { WorkspaceTrustEnablementService, WorkspaceTrustManagementService, WORKSPACE_TRUST_STORAGE_KEY } from 'vs/workbench/services/workspaces/common/workspaceTrust';
import { TestWorkspaceTrustEnablementService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { TestContextService, TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestContextService, TestStorageService, TestWorkspaceTrustEnablementService } from 'vs/workbench/test/common/workbenchTestServices';
suite('Workspace Trust', () => {
let instantiationService: TestInstantiationService;
@@ -36,14 +36,10 @@ suite('Diff editor input', () => {
}
}
let disposables: DisposableStore;
setup(() => {
disposables = new DisposableStore();
});
const disposables = new DisposableStore();
teardown(() => {
disposables.dispose();
disposables.clear();
});
test('basics', () => {
@@ -12,7 +12,7 @@ import { workbenchInstantiationService, TestServiceAccessor, TestEditorInput, re
import { Schemas } from 'vs/base/common/network';
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { toResource } from 'vs/base/test/common/utils';
import { ensureNoDisposablesAreLeakedInTestSuite, toResource } from 'vs/base/test/common/utils';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { whenEditorClosed } from 'vs/workbench/browser/editor';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -39,22 +39,11 @@ suite('Workbench editor utils', () => {
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
async function createServices(): Promise<TestServiceAccessor> {
const instantiationService = workbenchInstantiationService(undefined, disposables);
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
const editorService = instantiationService.createInstance(EditorService);
instantiationService.stub(IEditorService, editorService);
return instantiationService.createInstance(TestServiceAccessor);
}
setup(() => {
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
disposables.add(accessor.untitledTextEditorService);
disposables.add(registerTestFileEditor());
disposables.add(registerTestSideBySideEditor());
disposables.add(registerTestResourceEditor());
@@ -62,8 +51,6 @@ suite('Workbench editor utils', () => {
});
teardown(() => {
accessor.untitledTextEditorService.dispose();
disposables.clear();
});
@@ -99,8 +86,8 @@ suite('Workbench editor utils', () => {
});
test('EditorInputCapabilities', () => {
const testInput1 = new TestFileEditorInput(URI.file('resource1'), 'testTypeId');
const testInput2 = new TestFileEditorInput(URI.file('resource2'), 'testTypeId');
const testInput1 = disposables.add(new TestFileEditorInput(URI.file('resource1'), 'testTypeId'));
const testInput2 = disposables.add(new TestFileEditorInput(URI.file('resource2'), 'testTypeId'));
testInput1.capabilities = EditorInputCapabilities.None;
assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.None), true);
@@ -162,7 +149,7 @@ suite('Workbench editor utils', () => {
assert.ok(!EditorResourceAccessor.getCanonicalUri(null!));
assert.ok(!EditorResourceAccessor.getOriginalUri(null!));
const untitled = instantiationService.createInstance(UntitledTextEditorInput, service.create());
const untitled = disposables.add(instantiationService.createInstance(UntitledTextEditorInput, service.create()));
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(untitled)?.toString(), untitled.resource.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(untitled, { supportSideBySide: SideBySideEditor.PRIMARY })?.toString(), untitled.resource.toString());
@@ -182,7 +169,7 @@ suite('Workbench editor utils', () => {
assert.strictEqual(EditorResourceAccessor.getOriginalUri(untitled, { filterByScheme: [Schemas.file, Schemas.untitled] })?.toString(), untitled.resource.toString());
assert.ok(!EditorResourceAccessor.getOriginalUri(untitled, { filterByScheme: Schemas.file }));
const file = new TestEditorInput(URI.file('/some/path.txt'), 'editorResourceFileTest');
const file = disposables.add(new TestEditorInput(URI.file('/some/path.txt'), 'editorResourceFileTest'));
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(file)?.toString(), file.resource.toString());
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(file, { supportSideBySide: SideBySideEditor.PRIMARY })?.toString(), file.resource.toString());
@@ -246,7 +233,7 @@ suite('Workbench editor utils', () => {
const resource = URI.file('/some/path.txt');
const preferredResource = URI.file('/some/PATH.txt');
const fileWithPreferredResource = new TestEditorInputWithPreferredResource(URI.file('/some/path.txt'), URI.file('/some/PATH.txt'), 'editorResourceFileTest');
const fileWithPreferredResource = disposables.add(new TestEditorInputWithPreferredResource(URI.file('/some/path.txt'), URI.file('/some/PATH.txt'), 'editorResourceFileTest'));
assert.strictEqual(EditorResourceAccessor.getCanonicalUri(fileWithPreferredResource)?.toString(), resource.toString());
assert.strictEqual(EditorResourceAccessor.getOriginalUri(fileWithPreferredResource)?.toString(), preferredResource.toString());
@@ -363,13 +350,13 @@ suite('Workbench editor utils', () => {
assert.strictEqual(isEditorIdentifier(undefined), false);
assert.strictEqual(isEditorIdentifier('undefined'), false);
const testInput1 = new TestFileEditorInput(URI.file('resource1'), 'testTypeId');
const testInput1 = disposables.add(new TestFileEditorInput(URI.file('resource1'), 'testTypeId'));
assert.strictEqual(isEditorIdentifier(testInput1), false);
assert.strictEqual(isEditorIdentifier({ editor: testInput1, groupId: 3 }), true);
});
test('isEditorInputWithOptionsAndGroup', () => {
const editorInput = new TestFileEditorInput(URI.file('resource1'), 'testTypeId');
const editorInput = disposables.add(new TestFileEditorInput(URI.file('resource1'), 'testTypeId'));
assert.strictEqual(isEditorInput(editorInput), true);
assert.strictEqual(isEditorInputWithOptions(editorInput), false);
assert.strictEqual(isEditorInputWithOptionsAndGroup(editorInput), false);
@@ -434,6 +421,18 @@ suite('Workbench editor utils', () => {
return testWhenEditorClosed(false, true, toResource.call(this, '/path/index.txt'), toResource.call(this, '/test.html'));
});
async function createServices(): Promise<TestServiceAccessor> {
const instantiationService = workbenchInstantiationService(undefined, disposables);
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
const editorService = disposables.add(instantiationService.createInstance(EditorService));
instantiationService.stub(IEditorService, editorService);
return instantiationService.createInstance(TestServiceAccessor);
}
async function testWhenEditorClosed(sideBySide: boolean, custom: boolean, ...resources: URI[]): Promise<void> {
const accessor = await createServices();
@@ -453,4 +452,6 @@ suite('Workbench editor utils', () => {
await closedPromise;
}
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -15,18 +15,17 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
suite('TextDiffEditorModel', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
});
teardown(() => {
disposables.dispose();
disposables.clear();
});
test('basics', async () => {
@@ -22,7 +22,7 @@ suite('EditorInput', () => {
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
let disposables: DisposableStore;
const disposables = new DisposableStore();
const testResource: URI = URI.from({ scheme: 'random', path: '/path' });
const untypedResourceEditorInput: IResourceEditorInput = { resource: testResource, options: { override: DEFAULT_EDITOR_ASSOCIATION.id } };
@@ -52,7 +52,6 @@ suite('EditorInput', () => {
};
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
@@ -74,7 +73,7 @@ suite('EditorInput', () => {
});
teardown(() => {
disposables.dispose();
disposables.clear();
});
class MyEditorInput extends EditorInput {
@@ -19,16 +19,16 @@ import { URI } from 'vs/base/common/uri';
import { EditorPaneDescriptor, EditorPaneRegistry } from 'vs/workbench/browser/editor';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { DisposableStore, dispose } from 'vs/base/common/lifecycle';
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { TestStorageService, TestWorkspaceTrustManagementService } from 'vs/workbench/test/common/workbenchTestServices';
import { extUri } from 'vs/base/common/resources';
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { TestWorkspaceTrustManagementService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
const NullThemeService = new TestThemeService();
@@ -37,8 +37,11 @@ const editorInputRegistry: IEditorFactoryRegistry = Registry.as(EditorExtensions
class TestEditor extends EditorPane {
constructor(@ITelemetryService telemetryService: ITelemetryService) {
super('TestEditor', NullTelemetryService, NullThemeService, new TestStorageService());
constructor() {
const disposables = new DisposableStore();
super('TestEditor', NullTelemetryService, NullThemeService, disposables.add(new TestStorageService()));
this._register(disposables);
}
override getId(): string { return 'testEditor'; }
@@ -46,10 +49,13 @@ class TestEditor extends EditorPane {
protected createEditor(): any { }
}
export class OtherTestEditor extends EditorPane {
class OtherTestEditor extends EditorPane {
constructor(@ITelemetryService telemetryService: ITelemetryService) {
super('testOtherEditor', NullTelemetryService, NullThemeService, new TestStorageService());
constructor() {
const disposables = new DisposableStore();
super('testOtherEditor', NullTelemetryService, NullThemeService, disposables.add(new TestStorageService()));
this._register(disposables);
}
override getId(): string { return 'testOtherEditor'; }
@@ -106,9 +112,15 @@ class TestResourceEditorInput extends TextResourceEditorInput { }
suite('EditorPane', () => {
const disposables = new DisposableStore();
teardown(() => {
disposables.clear();
});
test('EditorPane API', async () => {
const editor = new TestEditor(NullTelemetryService);
const input = new OtherTestInput();
const editor = new TestEditor();
const input = disposables.add(new OtherTestInput());
const options = {};
assert(!editor.isVisible());
@@ -120,9 +132,6 @@ suite('EditorPane', () => {
editor.setVisible(true, group);
assert(editor.isVisible());
assert.strictEqual(editor.group, group);
input.onWillDispose(() => {
assert(false);
});
editor.dispose();
editor.clearInput();
editor.setVisible(false, group);
@@ -144,57 +153,46 @@ suite('EditorPane', () => {
const oldEditorsCnt = editorRegistry.getEditorPanes().length;
const oldInputCnt = editorRegistry.getEditors().length;
const dispose1 = editorRegistry.registerEditorPane(editorDescriptor1, [new SyncDescriptor(TestInput)]);
const dispose2 = editorRegistry.registerEditorPane(editorDescriptor2, [new SyncDescriptor(TestInput), new SyncDescriptor(OtherTestInput)]);
disposables.add(editorRegistry.registerEditorPane(editorDescriptor1, [new SyncDescriptor(TestInput)]));
disposables.add(editorRegistry.registerEditorPane(editorDescriptor2, [new SyncDescriptor(TestInput), new SyncDescriptor(OtherTestInput)]));
assert.strictEqual(editorRegistry.getEditorPanes().length, oldEditorsCnt + 2);
assert.strictEqual(editorRegistry.getEditors().length, oldInputCnt + 3);
assert.strictEqual(editorRegistry.getEditorPane(new TestInput()), editorDescriptor2);
assert.strictEqual(editorRegistry.getEditorPane(new OtherTestInput()), editorDescriptor2);
assert.strictEqual(editorRegistry.getEditorPane(disposables.add(new TestInput())), editorDescriptor2);
assert.strictEqual(editorRegistry.getEditorPane(disposables.add(new OtherTestInput())), editorDescriptor2);
assert.strictEqual(editorRegistry.getEditorPaneByType('id1'), editorDescriptor1);
assert.strictEqual(editorRegistry.getEditorPaneByType('id2'), editorDescriptor2);
assert(!editorRegistry.getEditorPaneByType('id3'));
dispose([dispose1, dispose2]);
});
test('Editor Pane Lookup favors specific class over superclass (match on specific class)', function () {
const d1 = EditorPaneDescriptor.create(TestEditor, 'id1', 'name');
const disposables = new DisposableStore();
disposables.add(registerTestResourceEditor());
disposables.add(editorRegistry.registerEditorPane(d1, [new SyncDescriptor(TestResourceEditorInput)]));
const inst = workbenchInstantiationService(undefined, disposables);
const editor = editorRegistry.getEditorPane(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined))!.instantiate(inst);
const editor = disposables.add(editorRegistry.getEditorPane(disposables.add(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined)))!.instantiate(inst));
assert.strictEqual(editor.getId(), 'testEditor');
const otherEditor = editorRegistry.getEditorPane(inst.createInstance(TextResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined))!.instantiate(inst);
const otherEditor = disposables.add(editorRegistry.getEditorPane(disposables.add(inst.createInstance(TextResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined)))!.instantiate(inst));
assert.strictEqual(otherEditor.getId(), 'workbench.editors.textResourceEditor');
disposables.dispose();
});
test('Editor Pane Lookup favors specific class over superclass (match on super class)', function () {
const disposables = new DisposableStore();
const inst = workbenchInstantiationService(undefined, disposables);
disposables.add(registerTestResourceEditor());
const editor = editorRegistry.getEditorPane(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined))!.instantiate(inst);
const editor = disposables.add(editorRegistry.getEditorPane(disposables.add(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined, undefined)))!.instantiate(inst));
assert.strictEqual('workbench.editors.textResourceEditor', editor.getId());
disposables.dispose();
});
test('Editor Input Serializer', function () {
const disposables = new DisposableStore();
const testInput = new TestEditorInput(URI.file('/fake'), 'testTypeId');
const testInput = disposables.add(new TestEditorInput(URI.file('/fake'), 'testTypeId'));
workbenchInstantiationService(undefined, disposables).invokeFunction(accessor => editorInputRegistry.start(accessor));
disposables.add(editorInputRegistry.registerEditorSerializer(testInput.typeId, TestInputSerializer));
@@ -206,8 +204,6 @@ suite('EditorPane', () => {
// throws when registering serializer for same type
assert.throws(() => editorInputRegistry.registerEditorSerializer(testInput.typeId, TestInputSerializer));
disposables.dispose();
});
test('EditorMemento - basics', function () {
@@ -228,7 +224,7 @@ suite('EditorPane', () => {
}
const rawMemento = Object.create(null);
let memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService, configurationService);
let memento = disposables.add(new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService, configurationService));
let res = memento.loadEditorState(testGroup0, URI.file('/A'));
assert.ok(!res);
@@ -263,7 +259,7 @@ suite('EditorPane', () => {
memento.saveState();
memento = new EditorMemento('id', 'key', rawMemento, 3, editorGroupService, configurationService);
memento = disposables.add(new EditorMemento('id', 'key', rawMemento, 3, editorGroupService, configurationService));
assert.ok(memento.loadEditorState(testGroup0, URI.file('/C')));
assert.ok(memento.loadEditorState(testGroup0, URI.file('/D')));
assert.ok(memento.loadEditorState(testGroup0, URI.file('/E')));
@@ -289,7 +285,7 @@ suite('EditorPane', () => {
interface TestViewState { line: number }
const rawMemento = Object.create(null);
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService, configurationService);
const memento = disposables.add(new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService, configurationService));
memento.saveEditorState(testGroup0, URI.file('/some/folder/file-1.txt'), { line: 1 });
memento.saveEditorState(testGroup0, URI.file('/some/folder/file-2.txt'), { line: 2 });
@@ -332,9 +328,9 @@ suite('EditorPane', () => {
}
const rawMemento = Object.create(null);
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService(), new TestTextResourceConfigurationService());
const memento = disposables.add(new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService(), new TestTextResourceConfigurationService()));
const testInputA = new TestEditorInput(URI.file('/A'));
const testInputA = disposables.add(new TestEditorInput(URI.file('/A')));
let res = memento.loadEditorState(testGroup0, testInputA);
assert.ok(!res);
@@ -370,9 +366,9 @@ suite('EditorPane', () => {
}
const rawMemento = Object.create(null);
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService(), new TestTextResourceConfigurationService());
const memento = disposables.add(new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, new TestEditorGroupsService(), new TestTextResourceConfigurationService()));
const testInputA = new TestEditorInput(URI.file('/A'));
const testInputA = disposables.add(new TestEditorInput(URI.file('/A')));
let res = memento.loadEditorState(testGroup0, testInputA);
assert.ok(!res);
@@ -388,7 +384,7 @@ suite('EditorPane', () => {
res = memento.loadEditorState(testGroup0, testInputA);
assert.ok(res);
const testInputB = new TestEditorInput(URI.file('/B'));
const testInputB = disposables.add(new TestEditorInput(URI.file('/B')));
res = memento.loadEditorState(testGroup0, testInputB);
assert.ok(!res);
@@ -422,7 +418,7 @@ suite('EditorPane', () => {
interface TestViewState { line: number }
const rawMemento = Object.create(null);
const memento = new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService, configurationService);
const memento = disposables.add(new EditorMemento<TestViewState>('id', 'key', rawMemento, 3, editorGroupService, configurationService));
const resource = URI.file('/some/folder/file-1.txt');
memento.saveEditorState(testGroup0, resource, { line: 1 });
@@ -459,7 +455,7 @@ suite('EditorPane', () => {
class TrustRequiredTestEditor extends EditorPane {
constructor(@ITelemetryService telemetryService: ITelemetryService) {
super('TestEditor', NullTelemetryService, NullThemeService, new TestStorageService());
super('TestEditor', NullTelemetryService, NullThemeService, disposables.add(new TestStorageService()));
}
override getId(): string { return 'trustRequiredTestEditor'; }
@@ -484,17 +480,15 @@ suite('EditorPane', () => {
}
}
const disposables = new DisposableStore();
const instantiationService = workbenchInstantiationService(undefined, disposables);
const workspaceTrustService = instantiationService.createInstance(TestWorkspaceTrustManagementService);
const workspaceTrustService = disposables.add(instantiationService.createInstance(TestWorkspaceTrustManagementService));
instantiationService.stub(IWorkspaceTrustManagementService, workspaceTrustService);
workspaceTrustService.setWorkspaceTrust(false);
const editorPart = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, editorPart);
const editorService = instantiationService.createInstance(EditorService);
const editorService = disposables.add(instantiationService.createInstance(EditorService));
instantiationService.stub(IEditorService, editorService);
const group = editorPart.activeGroup;
@@ -502,7 +496,7 @@ suite('EditorPane', () => {
const editorDescriptor = EditorPaneDescriptor.create(TrustRequiredTestEditor, 'id1', 'name');
disposables.add(editorRegistry.registerEditorPane(editorDescriptor, [new SyncDescriptor(TrustRequiredTestInput)]));
const testInput = new TrustRequiredTestInput();
const testInput = disposables.add(new TrustRequiredTestInput());
await group.openEditor(testInput);
assert.strictEqual(group.activeEditorPane?.getId(), WorkspaceTrustRequiredPlaceholderEditor.ID);
@@ -520,6 +514,8 @@ suite('EditorPane', () => {
workspaceTrustService.setWorkspaceTrust(false);
assert.strictEqual(await getEditorPaneIdAsync(), WorkspaceTrustRequiredPlaceholderEditor.ID);
dispose(disposables);
await group.closeAllEditors();
});
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -16,7 +16,7 @@ import { IFilesConfigurationService } from 'vs/workbench/services/filesConfigura
suite('ResourceEditorInput', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
class TestResourceEditorInput extends AbstractResourceEditorInput {
@@ -34,12 +34,11 @@ suite('ResourceEditorInput', () => {
}
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
});
teardown(() => {
disposables.dispose();
disposables.clear();
});
test('basics', async () => {
@@ -13,14 +13,10 @@ import { TestFileEditorInput, workbenchInstantiationService } from 'vs/workbench
suite('SideBySideEditorInput', () => {
let disposables: DisposableStore;
setup(() => {
disposables = new DisposableStore();
});
const disposables = new DisposableStore();
teardown(() => {
disposables.dispose();
disposables.clear();
});
class MyEditorInput extends EditorInput {
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { toResource } from 'vs/base/test/common/utils';
import { ensureNoDisposablesAreLeakedInTestSuite, toResource } from 'vs/base/test/common/utils';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { workbenchInstantiationService, TestServiceAccessor, registerTestFileEditor, createEditorPart, TestTextFileEditor } from 'vs/workbench/test/browser/workbenchTestServices';
import { IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
@@ -35,7 +35,7 @@ suite('TextEditorPane', () => {
const part = await createEditorPart(instantiationService, disposables);
instantiationService.stub(IEditorGroupsService, part);
const editorService = instantiationService.createInstance(EditorService);
const editorService = disposables.add(instantiationService.createInstance(EditorService));
instantiationService.stub(IEditorService, editorService);
return instantiationService.createInstance(TestServiceAccessor);
@@ -50,16 +50,16 @@ suite('TextEditorPane', () => {
assert.ok(pane && isEditorPaneWithSelection(pane));
const onDidFireSelectionEventOfEditType = new DeferredPromise<IEditorPaneSelectionChangeEvent>();
pane.onDidChangeSelection(e => {
disposables.add(pane.onDidChangeSelection(e => {
if (e.reason === EditorPaneSelectionChangeReason.EDIT) {
onDidFireSelectionEventOfEditType.complete(e);
}
});
}));
// Changing model reports selection change
// of EDIT kind
const model = await accessor.textFileService.files.resolve(resource) as IResolvedTextFileEditorModel;
const model = disposables.add(await accessor.textFileService.files.resolve(resource) as IResolvedTextFileEditorModel);
model.textEditorModel.setValue('Hello World');
const event = await onDidFireSelectionEventOfEditType.p;
@@ -83,6 +83,9 @@ suite('TextEditorPane', () => {
const newSelection = pane.getSelection();
assert.ok(newSelection);
assert.strictEqual(newSelection.compare(selection), EditorPaneSelectionCompareResult.IDENTICAL);
await model.revert();
await pane.group?.closeAllEditors();
});
test('TextEditorPaneSelection', function () {
@@ -96,4 +99,6 @@ suite('TextEditorPane', () => {
assert.strictEqual(sel1.compare(sel3), EditorPaneSelectionCompareResult.DIFFERENT);
assert.strictEqual(sel1.compare(sel4), EditorPaneSelectionCompareResult.DIFFERENT);
});
ensureNoDisposablesAreLeakedInTestSuite();
});
@@ -15,18 +15,18 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
suite('TextResourceEditorInput', () => {
let disposables: DisposableStore;
const disposables = new DisposableStore();
let instantiationService: IInstantiationService;
let accessor: TestServiceAccessor;
setup(() => {
disposables = new DisposableStore();
instantiationService = workbenchInstantiationService(undefined, disposables);
accessor = instantiationService.createInstance(TestServiceAccessor);
});
teardown(() => {
disposables.dispose();
disposables.clear();
});
test('basics', async () => {
@@ -99,7 +99,7 @@ import { IInputBox, IInputOptions, IPickOptions, IQuickInputButton, IQuickInputS
import { QuickInputService } from 'vs/workbench/services/quickinput/browser/quickInputService';
import { IListService } from 'vs/platform/list/browser/listService';
import { win32, posix } from 'vs/base/common/path';
import { TestContextService, TestStorageService, TestTextResourcePropertiesService, TestExtensionService, TestProductService, createFileStat, TestLoggerService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestContextService, TestStorageService, TestTextResourcePropertiesService, TestExtensionService, TestProductService, createFileStat, TestLoggerService, TestWorkspaceTrustManagementService, TestWorkspaceTrustRequestService } from 'vs/workbench/test/common/workbenchTestServices';
import { IViewsService, IView, ViewContainer, ViewContainerLocation } from 'vs/workbench/common/views';
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
@@ -121,7 +121,6 @@ import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/u
import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor';
import { IEnterWorkspaceResult, IRecent, IRecentlyOpened, IWorkspaceFolderCreationData, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceTrustManagementService, IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
import { TestWorkspaceTrustManagementService, TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
import { IExtensionTerminalProfile, IShellLaunchConfig, ITerminalBackend, ITerminalProfile, TerminalIcon, TerminalLocation, TerminalShellType } from 'vs/platform/terminal/common/terminal';
import { ICreateTerminalOptions, IDeserializedTerminalEditorInput, ITerminalEditorService, ITerminalGroup, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, TerminalEditorLocation } from 'vs/workbench/contrib/terminal/browser/terminal';
import { assertIsDefined } from 'vs/base/common/types';
@@ -188,14 +187,14 @@ Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerFile
export class TestTextResourceEditor extends TextResourceEditor {
protected override createEditorControl(parent: HTMLElement, configuration: any): void {
this.editorControl = this.instantiationService.createInstance(TestCodeEditor, parent, configuration, {});
this.editorControl = this._register(this.instantiationService.createInstance(TestCodeEditor, parent, configuration, {}));
}
}
export class TestTextFileEditor extends TextFileEditor {
protected override createEditorControl(parent: HTMLElement, configuration: any): void {
this.editorControl = this.instantiationService.createInstance(TestCodeEditor, parent, configuration, { contributions: [] });
this.editorControl = this._register(this.instantiationService.createInstance(TestCodeEditor, parent, configuration, { contributions: [] }));
}
setSelection(selection: Selection | undefined, reason: EditorPaneSelectionChangeReason): void {
@@ -243,7 +242,7 @@ export function workbenchInstantiationService(
},
disposables: Pick<DisposableStore, 'add'> = new DisposableStore()
): TestInstantiationService {
const instantiationService = disposables.add(new TestInstantiationService(new ServiceCollection([ILifecycleService, new TestLifecycleService()])));
const instantiationService = disposables.add(new TestInstantiationService(new ServiceCollection([ILifecycleService, disposables.add(new TestLifecycleService())])));
instantiationService.stub(IEditorWorkerService, new TestEditorWorkerService());
instantiationService.stub(IWorkingCopyService, disposables.add(new TestWorkingCopyService()));
@@ -285,15 +284,15 @@ export function workbenchInstantiationService(
instantiationService.stub(IThemeService, themeService);
instantiationService.stub(ILanguageConfigurationService, disposables.add(new TestLanguageConfigurationService()));
instantiationService.stub(IModelService, disposables.add(instantiationService.createInstance(ModelService)));
const fileService = overrides?.fileService ? overrides.fileService(instantiationService) : new TestFileService();
const fileService = overrides?.fileService ? overrides.fileService(instantiationService) : disposables.add(new TestFileService());
instantiationService.stub(IFileService, fileService);
const uriIdentityService = new UriIdentityService(fileService);
disposables.add(uriIdentityService);
instantiationService.stub(IFilesConfigurationService, disposables.add(new TestFilesConfigurationService(contextKeyService, configService, workspaceContextService, environmentService, uriIdentityService, fileService)));
instantiationService.stub(IUriIdentityService, uriIdentityService);
instantiationService.stub(IUriIdentityService, disposables.add(uriIdentityService));
const userDataProfilesService = instantiationService.stub(IUserDataProfilesService, disposables.add(new UserDataProfilesService(environmentService, fileService, uriIdentityService, new NullLogService())));
instantiationService.stub(IUserDataProfileService, disposables.add(new UserDataProfileService(userDataProfilesService.defaultProfile, userDataProfilesService)));
instantiationService.stub(IWorkingCopyBackupService, overrides?.workingCopyBackupService ? overrides?.workingCopyBackupService(instantiationService) : new TestWorkingCopyBackupService());
instantiationService.stub(IWorkingCopyBackupService, overrides?.workingCopyBackupService ? overrides?.workingCopyBackupService(instantiationService) : disposables.add(new TestWorkingCopyBackupService()));
instantiationService.stub(ITelemetryService, NullTelemetryService);
instantiationService.stub(INotificationService, new TestNotificationService());
instantiationService.stub(IUntitledTextEditorService, disposables.add(instantiationService.createInstance(UntitledTextEditorService)));
@@ -323,7 +322,8 @@ export function workbenchInstantiationService(
const hoverService = instantiationService.stub(IHoverService, instantiationService.createInstance(TestHoverService));
instantiationService.stub(IQuickInputService, disposables.add(new QuickInputService(configService, instantiationService, keybindingService, contextKeyService, themeService, layoutService, hoverService)));
instantiationService.stub(IWorkspacesService, new TestWorkspacesService());
instantiationService.stub(IWorkspaceTrustManagementService, new TestWorkspaceTrustManagementService());
instantiationService.stub(IWorkspaceTrustManagementService, disposables.add(new TestWorkspaceTrustManagementService()));
instantiationService.stub(IWorkspaceTrustRequestService, disposables.add(new TestWorkspaceTrustRequestService(false)));
instantiationService.stub(ITerminalInstanceService, new TestTerminalInstanceService());
instantiationService.stub(IElevatedFileService, new BrowserElevatedFileService());
instantiationService.stub(IRemoteSocketFactoryService, new RemoteSocketFactoryService());
@@ -1195,17 +1195,20 @@ export class InMemoryTestWorkingCopyBackupService extends BrowserWorkingCopyBack
discardedBackups: IWorkingCopyIdentifier[];
constructor() {
const disposables = new DisposableStore();
const environmentService = TestEnvironmentService;
const logService = new NullLogService();
const fileService = new FileService(logService);
fileService.registerProvider(Schemas.file, new InMemoryFileSystemProvider());
fileService.registerProvider(Schemas.vscodeUserData, new InMemoryFileSystemProvider());
const fileService = disposables.add(new FileService(logService));
disposables.add(fileService.registerProvider(Schemas.file, disposables.add(new InMemoryFileSystemProvider())));
disposables.add(fileService.registerProvider(Schemas.vscodeUserData, disposables.add(new InMemoryFileSystemProvider())));
super(new TestContextService(TestWorkspace), environmentService, fileService, logService);
this.backupResourceJoiners = [];
this.discardBackupJoiners = [];
this.discardedBackups = [];
this._register(disposables);
}
testGetFileService(): IFileService {
@@ -1246,26 +1249,26 @@ export class InMemoryTestWorkingCopyBackupService extends BrowserWorkingCopyBack
}
}
export class TestLifecycleService implements ILifecycleService {
export class TestLifecycleService extends Disposable implements ILifecycleService {
declare readonly _serviceBrand: undefined;
phase!: LifecyclePhase;
startupKind!: StartupKind;
private readonly _onBeforeShutdown = new Emitter<InternalBeforeShutdownEvent>();
private readonly _onBeforeShutdown = this._register(new Emitter<InternalBeforeShutdownEvent>());
get onBeforeShutdown(): Event<InternalBeforeShutdownEvent> { return this._onBeforeShutdown.event; }
private readonly _onBeforeShutdownError = new Emitter<BeforeShutdownErrorEvent>();
private readonly _onBeforeShutdownError = this._register(new Emitter<BeforeShutdownErrorEvent>());
get onBeforeShutdownError(): Event<BeforeShutdownErrorEvent> { return this._onBeforeShutdownError.event; }
private readonly _onShutdownVeto = new Emitter<void>();
private readonly _onShutdownVeto = this._register(new Emitter<void>());
get onShutdownVeto(): Event<void> { return this._onShutdownVeto.event; }
private readonly _onWillShutdown = new Emitter<WillShutdownEvent>();
private readonly _onWillShutdown = this._register(new Emitter<WillShutdownEvent>());
get onWillShutdown(): Event<WillShutdownEvent> { return this._onWillShutdown.event; }
private readonly _onDidShutdown = new Emitter<void>();
private readonly _onDidShutdown = this._register(new Emitter<void>());
get onDidShutdown(): Event<void> { return this._onDidShutdown.event; }
async when(): Promise<void> { }
@@ -1488,12 +1491,14 @@ export class TestEditorInput extends EditorInput {
}
export function registerTestEditor(id: string, inputs: SyncDescriptor<EditorInput>[], serializerInputId?: string): IDisposable {
const disposables = new DisposableStore();
class TestEditor extends EditorPane {
private _scopedContextKeyService: IContextKeyService;
constructor() {
super(id, NullTelemetryService, new TestThemeService(), new TestStorageService());
super(id, NullTelemetryService, new TestThemeService(), disposables.add(new TestStorageService()));
this._scopedContextKeyService = new MockContextKeyService();
}
@@ -1512,8 +1517,6 @@ export function registerTestEditor(id: string, inputs: SyncDescriptor<EditorInpu
}
}
const disposables = new DisposableStore();
disposables.add(Registry.as<IEditorPaneRegistry>(Extensions.EditorPane).registerEditorPane(EditorPaneDescriptor.create(TestEditor, id, 'Test Editor Control'), inputs));
if (serializerInputId) {
@@ -2089,3 +2092,22 @@ export class TestWebExtensionsScannerService implements IWebExtensionsScannerSer
throw new Error('Method not implemented.');
}
}
export async function workbenchTeardown(instantiationService: IInstantiationService): Promise<void> {
return instantiationService.invokeFunction(async accessor => {
const workingCopyService = accessor.get(IWorkingCopyService);
const editorGroupService = accessor.get(IEditorGroupsService);
for (const workingCopy of workingCopyService.workingCopies) {
await workingCopy.revert();
}
for (const group of editorGroupService.groups) {
await group.closeAllEditors();
}
for (const group of editorGroupService.groups) {
editorGroupService.removeGroup(group);
}
});
}
@@ -28,6 +28,7 @@ import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { AutoSaveMode, IAutoSaveConfiguration, IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { IWorkspaceTrustEnablementService, IWorkspaceTrustManagementService, IWorkspaceTrustRequestService, IWorkspaceTrustTransitionParticipant, IWorkspaceTrustUriInfo, WorkspaceTrustRequestOptions, WorkspaceTrustUriResponse } from 'vs/platform/workspace/common/workspaceTrust';
export class TestLoggerService extends AbstractLoggerService {
constructor(logsHome?: URI) {
@@ -315,3 +316,141 @@ export const NullFilesConfigurationService = new class implements IFilesConfigur
async updateReadonly(resource: URI, readonly: boolean | 'toggle' | 'reset'): Promise<void> { }
preventSaveConflicts(resource: URI, language?: string | undefined): boolean { throw new Error('Method not implemented.'); }
};
export class TestWorkspaceTrustEnablementService implements IWorkspaceTrustEnablementService {
_serviceBrand: undefined;
constructor(private isEnabled: boolean = true) { }
isWorkspaceTrustEnabled(): boolean {
return this.isEnabled;
}
}
export class TestWorkspaceTrustManagementService extends Disposable implements IWorkspaceTrustManagementService {
_serviceBrand: undefined;
private _onDidChangeTrust = this._register(new Emitter<boolean>());
onDidChangeTrust = this._onDidChangeTrust.event;
private _onDidChangeTrustedFolders = this._register(new Emitter<void>());
onDidChangeTrustedFolders = this._onDidChangeTrustedFolders.event;
private _onDidInitiateWorkspaceTrustRequestOnStartup = this._register(new Emitter<void>());
onDidInitiateWorkspaceTrustRequestOnStartup = this._onDidInitiateWorkspaceTrustRequestOnStartup.event;
constructor(
private trusted: boolean = true
) {
super();
}
get acceptsOutOfWorkspaceFiles(): boolean {
throw new Error('Method not implemented.');
}
set acceptsOutOfWorkspaceFiles(value: boolean) {
throw new Error('Method not implemented.');
}
addWorkspaceTrustTransitionParticipant(participant: IWorkspaceTrustTransitionParticipant): IDisposable {
throw new Error('Method not implemented.');
}
getTrustedUris(): URI[] {
throw new Error('Method not implemented.');
}
setParentFolderTrust(trusted: boolean): Promise<void> {
throw new Error('Method not implemented.');
}
getUriTrustInfo(uri: URI): Promise<IWorkspaceTrustUriInfo> {
throw new Error('Method not implemented.');
}
async setTrustedUris(folders: URI[]): Promise<void> {
throw new Error('Method not implemented.');
}
async setUrisTrust(uris: URI[], trusted: boolean): Promise<void> {
throw new Error('Method not implemented.');
}
canSetParentFolderTrust(): boolean {
throw new Error('Method not implemented.');
}
canSetWorkspaceTrust(): boolean {
throw new Error('Method not implemented.');
}
isWorkspaceTrusted(): boolean {
return this.trusted;
}
isWorkspaceTrustForced(): boolean {
return false;
}
get workspaceTrustInitialized(): Promise<void> {
return Promise.resolve();
}
get workspaceResolved(): Promise<void> {
return Promise.resolve();
}
async setWorkspaceTrust(trusted: boolean): Promise<void> {
if (this.trusted !== trusted) {
this.trusted = trusted;
this._onDidChangeTrust.fire(this.trusted);
}
}
}
export class TestWorkspaceTrustRequestService extends Disposable implements IWorkspaceTrustRequestService {
_serviceBrand: any;
private readonly _onDidInitiateOpenFilesTrustRequest = this._register(new Emitter<void>());
readonly onDidInitiateOpenFilesTrustRequest = this._onDidInitiateOpenFilesTrustRequest.event;
private readonly _onDidInitiateWorkspaceTrustRequest = this._register(new Emitter<WorkspaceTrustRequestOptions>());
readonly onDidInitiateWorkspaceTrustRequest = this._onDidInitiateWorkspaceTrustRequest.event;
private readonly _onDidInitiateWorkspaceTrustRequestOnStartup = this._register(new Emitter<void>());
readonly onDidInitiateWorkspaceTrustRequestOnStartup = this._onDidInitiateWorkspaceTrustRequestOnStartup.event;
constructor(private readonly _trusted: boolean) {
super();
}
requestOpenUrisHandler = async (uris: URI[]) => {
return WorkspaceTrustUriResponse.Open;
};
requestOpenFilesTrust(uris: URI[]): Promise<WorkspaceTrustUriResponse> {
return this.requestOpenUrisHandler(uris);
}
async completeOpenFilesTrustRequest(result: WorkspaceTrustUriResponse, saveResponse: boolean): Promise<void> {
throw new Error('Method not implemented.');
}
cancelWorkspaceTrustRequest(): void {
throw new Error('Method not implemented.');
}
async completeWorkspaceTrustRequest(trusted?: boolean): Promise<void> {
throw new Error('Method not implemented.');
}
async requestWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Promise<boolean> {
return this._trusted;
}
requestWorkspaceTrustOnStartup(): void {
throw new Error('Method not implemented.');
}
}
@@ -8,7 +8,7 @@ import { workbenchInstantiationService as browserWorkbenchInstantiationService,
import { ISharedProcessService } from 'vs/platform/ipc/electron-sandbox/services';
import { INativeHostService, IOSProperties, IOSStatistics } from 'vs/platform/native/common/native';
import { VSBuffer, VSBufferReadable, VSBufferReadableStream } from 'vs/base/common/buffer';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { IFileDialogService, INativeOpenDialogOptions } from 'vs/platform/dialogs/common/dialogs';
import { IPartsSplash } from 'vs/platform/theme/common/themeService';
@@ -52,11 +52,8 @@ export class TestSharedProcessService implements ISharedProcessService {
declare readonly _serviceBrand: undefined;
createRawConnection(): never { throw new Error('Not Implemented'); }
getChannel(channelName: string): any { return undefined; }
registerChannel(channelName: string, channel: any): void { }
notifyRestored(): void { }
}
@@ -178,7 +175,7 @@ export function workbenchInstantiationService(overrides?: {
textEditorService?: (instantiationService: IInstantiationService) => ITextEditorService;
}, disposables = new DisposableStore()): ITestInstantiationService {
const instantiationService = browserWorkbenchInstantiationService({
workingCopyBackupService: (instantiationService: IInstantiationService) => new TestNativeWorkingCopyBackupService(),
workingCopyBackupService: () => disposables.add(new TestNativeWorkingCopyBackupService()),
...overrides
}, disposables);
@@ -216,7 +213,7 @@ export class TestNativeTextFileServiceWithEncodingOverrides extends NativeTextFi
}
}
export class TestNativeWorkingCopyBackupService extends NativeWorkingCopyBackupService {
export class TestNativeWorkingCopyBackupService extends NativeWorkingCopyBackupService implements IDisposable {
private backupResourceJoiners: Function[];
private discardBackupJoiners: Function[];
@@ -231,15 +228,18 @@ export class TestNativeWorkingCopyBackupService extends NativeWorkingCopyBackupS
const lifecycleService = new TestLifecycleService();
super(environmentService as any, fileService, logService, lifecycleService);
const inMemoryFileSystemProvider = new InMemoryFileSystemProvider();
fileService.registerProvider(Schemas.inMemory, inMemoryFileSystemProvider);
fileService.registerProvider(Schemas.vscodeUserData, new FileUserDataProvider(Schemas.file, inMemoryFileSystemProvider, Schemas.vscodeUserData, logService));
const inMemoryFileSystemProvider = this._register(new InMemoryFileSystemProvider());
this._register(fileService.registerProvider(Schemas.inMemory, inMemoryFileSystemProvider));
this._register(fileService.registerProvider(Schemas.vscodeUserData, this._register(new FileUserDataProvider(Schemas.file, inMemoryFileSystemProvider, Schemas.vscodeUserData, logService))));
this.backupResourceJoiners = [];
this.discardBackupJoiners = [];
this.discardedBackups = [];
this.pendingBackupsArr = [];
this.discardedAllBackups = false;
this._register(fileService);
this._register(lifecycleService);
}
testGetFileService(): IFileService {