configurationEditingService.test.ts 17.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import assert = require('assert');
import os = require('os');
import path = require('path');
import fs = require('fs');
import * as json from 'vs/base/common/json';
J
Johannes Rieken 已提交
13 14
import { TPromise } from 'vs/base/common/winjs.base';
import { Registry } from 'vs/platform/platform';
J
Joao Moreno 已提交
15 16
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { parseArgs } from 'vs/platform/environment/node/argv';
J
Johannes Rieken 已提交
17 18
import { WorkspaceContextService, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
19
import extfs = require('vs/base/node/extfs');
20
import { workbenchInstantiationService, TestTextFileService } from 'vs/workbench/test/workbenchTestServices';
21
import uuid = require('vs/base/common/uuid');
J
Johannes Rieken 已提交
22 23
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { WorkspaceConfigurationService } from 'vs/workbench/services/configuration/node/configurationService';
24
import URI from 'vs/base/common/uri';
J
Johannes Rieken 已提交
25
import { FileService } from 'vs/workbench/services/files/node/fileService';
26
import { ConfigurationEditingService } from 'vs/workbench/services/configuration/node/configurationEditingService';
J
Johannes Rieken 已提交
27 28 29 30
import { ConfigurationTarget, IConfigurationEditingError, ConfigurationEditingErrorCode } from 'vs/workbench/services/configuration/common/configurationEditing';
import { IFileService } from 'vs/platform/files/common/files';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
31
import { WORKSPACE_STANDALONE_CONFIGURATIONS } from 'vs/workbench/services/configuration/common/configuration';
J
Johannes Rieken 已提交
32 33 34 35
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
B
Benjamin Pasero 已提交
36
import { IMessageService } from 'vs/platform/message/common/message';
37 38
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { IWindowsService } from 'vs/platform/windows/common/windows';
B
Benjamin Pasero 已提交
39
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
40 41 42 43 44 45 46 47 48 49

class SettingsTestEnvironmentService extends EnvironmentService {

	constructor(args: ParsedArgs, _execPath: string, private customAppSettingsHome) {
		super(args, _execPath);
	}

	get appSettingsPath(): string { return this.customAppSettingsHome; }
}

50
class TestDirtyTextFileService extends TestTextFileService {
51

52 53 54 55 56 57 58 59 60
	constructor(
		private dirty: boolean,
		@ILifecycleService lifecycleService: ILifecycleService,
		@IWorkspaceContextService contextService: IWorkspaceContextService,
		@IConfigurationService configurationService: IConfigurationService,
		@ITelemetryService telemetryService: ITelemetryService,
		@IWorkbenchEditorService editorService: IWorkbenchEditorService,
		@IFileService fileService: IFileService,
		@IUntitledEditorService untitledEditorService: IUntitledEditorService,
61
		@IInstantiationService instantiationService: IInstantiationService,
62 63
		@IMessageService messageService: IMessageService,
		@IBackupFileService backupFileService: IBackupFileService,
B
Benjamin Pasero 已提交
64 65
		@IWindowsService windowsService: IWindowsService,
		@IEditorGroupService editorGroupService: IEditorGroupService
66
	) {
B
Benjamin Pasero 已提交
67
		super(lifecycleService, contextService, configurationService, telemetryService, editorService, fileService, untitledEditorService, instantiationService, messageService, backupFileService, windowsService, editorGroupService);
68 69
	}

70 71
	public isDirty(resource?: URI): boolean {
		return this.dirty;
72 73 74 75 76
	}
}

suite('WorkspaceConfigurationEditingService - Node', () => {

77
	function createWorkspace(callback: (workspaceDir: string, globalSettingsFile: string, cleanUp: (done: () => void, error?: Error) => void, error: Error) => void): void {
78 79 80 81 82 83 84
		const id = uuid.generateUuid();
		const parentDir = path.join(os.tmpdir(), 'vsctests', id);
		const workspaceDir = path.join(parentDir, 'workspaceconfig', id);
		const workspaceSettingsDir = path.join(workspaceDir, '.vscode');
		const globalSettingsFile = path.join(workspaceDir, 'config.json');

		extfs.mkdirp(workspaceSettingsDir, 493, (error) => {
85 86 87 88 89 90 91 92
			callback(workspaceDir, globalSettingsFile, (done, error) => {
				extfs.del(parentDir, os.tmpdir(), () => { }, () => {
					if (error) {
						assert.fail(error);
					}

					done();
				});
93
			}, error);
94 95 96 97 98 99
		});
	}

	function createServices(workspaceDir: string, globalSettingsFile: string, dirty?: boolean, noWorkspace?: boolean): TPromise<{ configurationService: WorkspaceConfigurationService, configurationEditingService: ConfigurationEditingService }> {
		const workspaceContextService = new WorkspaceContextService(noWorkspace ? null : { resource: URI.file(workspaceDir) });
		const environmentService = new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, globalSettingsFile);
100 101
		const fileService = new FileService(noWorkspace ? null : workspaceDir, { disableWatcher: true });
		const configurationService = new WorkspaceConfigurationService(workspaceContextService, environmentService);
102
		const textFileService = workbenchInstantiationService().createInstance(TestDirtyTextFileService, dirty);
103 104 105

		return configurationService.initialize().then(() => {
			return {
B
Benjamin Pasero 已提交
106
				configurationEditingService: new ConfigurationEditingService(configurationService, workspaceContextService, environmentService, fileService, null, textFileService),
107
				configurationService
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
			};
		});
	}

	const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration);
	configurationRegistry.registerConfiguration({
		'id': '_test',
		'type': 'object',
		'properties': {
			'configurationEditing.service.testSetting': {
				'type': 'string',
				'default': 'isSet'
			},
			'configurationEditing.service.testSettingTwo': {
				'type': 'string',
				'default': 'isSet'
			},
			'configurationEditing.service.testSettingThree': {
				'type': 'string',
				'default': 'isSet'
			}
		}
	});

	test('errors cases - invalid key', (done: () => void) => {
133 134 135 136 137
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
138
			createServices(workspaceDir, globalSettingsFile, false, true /* no workspace */).done(services => {
139
				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'unknown.key', value: 'value' }).then(res => {
140
				}, (error: IConfigurationEditingError) => {
141
					assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY);
142 143 144
					services.configurationService.dispose();
					cleanUp(done);
				});
145
			}, error => cleanUp(done, error));
146 147 148
		});
	});

149
	test('errors cases - invalid target', (done: () => void) => {
150 151 152 153 154
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
155
			createServices(workspaceDir, globalSettingsFile).done(services => {
156
				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'tasks.something', value: 'value' }).then(res => {
157
				}, (error: IConfigurationEditingError) => {
158 159 160 161
					assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_TARGET);
					services.configurationService.dispose();
					cleanUp(done);
				});
162
			}, error => cleanUp(done, error));
163 164 165
		});
	});

166
	test('errors cases - no workspace', (done: () => void) => {
167 168 169 170 171
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
172
			createServices(workspaceDir, globalSettingsFile, false, true /* no workspace */).done(services => {
173
				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'configurationEditing.service.testSetting', value: 'value' }).then(res => {
174 175
				}, (error: IConfigurationEditingError) => {
					assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_NO_WORKSPACE_OPENED);
176 177 178
					services.configurationService.dispose();
					cleanUp(done);
				});
179
			}, error => cleanUp(done, error));
180 181 182 183
		});
	});

	test('errors cases - invalid configuration', (done: () => void) => {
184 185 186 187 188
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
189
			createServices(workspaceDir, globalSettingsFile).done(services => {
190 191
				fs.writeFileSync(globalSettingsFile, ',,,,,,,,,,,,,,');

192
				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }).then(res => {
193 194
				}, (error: IConfigurationEditingError) => {
					assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_INVALID_CONFIGURATION);
195 196 197
					services.configurationService.dispose();
					cleanUp(done);
				});
198
			}, error => cleanUp(done, error));
199 200 201 202
		});
	});

	test('errors cases - dirty', (done: () => void) => {
203 204 205 206 207
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
208
			createServices(workspaceDir, globalSettingsFile, true).done(services => {
209
				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }).then(res => {
210 211
				}, (error: IConfigurationEditingError) => {
					assert.equal(error.code, ConfigurationEditingErrorCode.ERROR_CONFIGURATION_FILE_DIRTY);
212 213 214
					services.configurationService.dispose();
					cleanUp(done);
				});
215
			}, error => cleanUp(done, error));
216 217 218 219
		});
	});

	test('write one setting - empty file', (done: () => void) => {
220 221 222 223 224
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
225
			createServices(workspaceDir, globalSettingsFile).done(services => {
226
				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }).then(res => {
227 228 229
					const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
					const parsed = json.parse(contents);
					assert.equal(parsed['configurationEditing.service.testSetting'], 'value');
230
					assert.equal(services.configurationService.lookup('configurationEditing.service.testSetting').value, 'value');
231 232 233 234

					services.configurationService.dispose();
					cleanUp(done);
				});
235
			}, error => cleanUp(done, error));
236 237 238 239
		});
	});

	test('write one setting - existing file', (done: () => void) => {
240 241 242 243 244
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
245
			createServices(workspaceDir, globalSettingsFile).done(services => {
246 247
				fs.writeFileSync(globalSettingsFile, '{ "my.super.setting": "my.super.value" }');

248
				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, { key: 'configurationEditing.service.testSetting', value: 'value' }).then(res => {
249 250 251 252 253
					const contents = fs.readFileSync(globalSettingsFile).toString('utf8');
					const parsed = json.parse(contents);
					assert.equal(parsed['configurationEditing.service.testSetting'], 'value');
					assert.equal(parsed['my.super.setting'], 'my.super.value');

254 255 256
					assert.equal(services.configurationService.lookup('configurationEditing.service.testSetting').value, 'value');
					assert.equal(services.configurationService.lookup('my.super.setting').value, 'my.super.value');

257 258 259
					services.configurationService.dispose();
					cleanUp(done);
				});
260
			}, error => cleanUp(done, error));
261 262 263
		});
	});

264
	test('write workspace standalone setting - empty file', (done: () => void) => {
265 266 267 268 269
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
270
			createServices(workspaceDir, globalSettingsFile).done(services => {
271 272 273
				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks.service.testSetting', value: 'value' }).then(res => {
					const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
					const contents = fs.readFileSync(target).toString('utf8');
274
					const parsed = json.parse(contents);
275 276
					assert.equal(parsed['service.testSetting'], 'value');
					assert.equal(services.configurationService.lookup('tasks.service.testSetting').value, 'value');
277

278 279 280
					services.configurationService.dispose();
					cleanUp(done);
				});
281
			}, error => cleanUp(done, error));
282 283 284
		});
	});

285
	test('write workspace standalone setting - existing file', (done: () => void) => {
286 287 288 289 290
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
291
			createServices(workspaceDir, globalSettingsFile).done(services => {
292
				const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']);
293

294
				fs.writeFileSync(target, '{ "my.super.setting": "my.super.value" }');
295

296 297 298 299
				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'launch.service.testSetting', value: 'value' }).then(res => {
					const contents = fs.readFileSync(target).toString('utf8');
					const parsed = json.parse(contents);
					assert.equal(parsed['service.testSetting'], 'value');
300 301
					assert.equal(parsed['my.super.setting'], 'my.super.value');

302 303
					assert.equal(services.configurationService.lookup('launch.service.testSetting').value, 'value');
					assert.equal(services.configurationService.lookup('launch.my.super.setting').value, 'my.super.value');
304

305 306 307
					services.configurationService.dispose();
					cleanUp(done);
				});
308
			}, error => cleanUp(done, error));
309 310
		});
	});
311 312

	test('write workspace standalone setting - empty file - full JSON', (done: () => void) => {
313 314 315 316 317
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
318
			createServices(workspaceDir, globalSettingsFile).done(services => {
319 320 321 322 323 324 325 326 327 328 329
				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }).then(res => {
					const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
					const contents = fs.readFileSync(target).toString('utf8');
					const parsed = json.parse(contents);

					assert.equal(parsed['version'], '1.0.0');
					assert.equal(parsed['tasks'][0]['taskName'], 'myTask');

					services.configurationService.dispose();
					cleanUp(done);
				});
330
			}, error => cleanUp(done, error));
331 332 333 334
		});
	});

	test('write workspace standalone setting - existing file - full JSON', (done: () => void) => {
335 336 337 338 339
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}

B
Benjamin Pasero 已提交
340
			createServices(workspaceDir, globalSettingsFile).done(services => {
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
				const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']);

				fs.writeFileSync(target, '{ "my.super.setting": "my.super.value" }');

				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }).then(res => {
					const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
					const contents = fs.readFileSync(target).toString('utf8');
					const parsed = json.parse(contents);

					assert.equal(parsed['version'], '1.0.0');
					assert.equal(parsed['tasks'][0]['taskName'], 'myTask');

					services.configurationService.dispose();
					cleanUp(done);
				});
356
			}, error => cleanUp(done, error));
357 358
		});
	});
359 360

	test('write workspace standalone setting - existing file with JSON errors - full JSON', (done: () => void) => {
361 362 363 364
		createWorkspace((workspaceDir, globalSettingsFile, cleanUp, error) => {
			if (error) {
				return cleanUp(done, error);
			}
365

B
Benjamin Pasero 已提交
366
			createServices(workspaceDir, globalSettingsFile).done(services => {
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
				const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['launch']);

				fs.writeFileSync(target, '{ "my.super.setting": '); // invalid JSON

				return services.configurationEditingService.writeConfiguration(ConfigurationTarget.WORKSPACE, { key: 'tasks', value: { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] } }).then(res => {
					const target = path.join(workspaceDir, WORKSPACE_STANDALONE_CONFIGURATIONS['tasks']);
					const contents = fs.readFileSync(target).toString('utf8');
					const parsed = json.parse(contents);

					assert.equal(parsed['version'], '1.0.0');
					assert.equal(parsed['tasks'][0]['taskName'], 'myTask');

					services.configurationService.dispose();
					cleanUp(done);
				});
382
			}, error => cleanUp(done, error));
383 384
		});
	});
385
});