Path: blob/main/src/vs/platform/configuration/test/common/configurationService.test.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import { VSBuffer } from '../../../../base/common/buffer.js';7import { Event } from '../../../../base/common/event.js';8import { Schemas } from '../../../../base/common/network.js';9import { URI } from '../../../../base/common/uri.js';10import { runWithFakedTimers } from '../../../../base/test/common/timeTravelScheduler.js';11import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';12import { ConfigurationTarget, isConfigured } from '../../common/configuration.js';13import { Extensions as ConfigurationExtensions, IConfigurationRegistry } from '../../common/configurationRegistry.js';14import { ConfigurationService } from '../../common/configurationService.js';15import { IFileService } from '../../../files/common/files.js';16import { FileService } from '../../../files/common/fileService.js';17import { InMemoryFileSystemProvider } from '../../../files/common/inMemoryFilesystemProvider.js';18import { NullLogService } from '../../../log/common/log.js';19import { FilePolicyService } from '../../../policy/common/filePolicyService.js';20import { NullPolicyService } from '../../../policy/common/policy.js';21import { Registry } from '../../../registry/common/platform.js';2223suite('ConfigurationService.test.ts', () => {2425const disposables = ensureNoDisposablesAreLeakedInTestSuite();2627let fileService: IFileService;28let settingsResource: URI;2930setup(async () => {31fileService = disposables.add(new FileService(new NullLogService()));32const diskFileSystemProvider = disposables.add(new InMemoryFileSystemProvider());33disposables.add(fileService.registerProvider(Schemas.file, diskFileSystemProvider));34settingsResource = URI.file('settings.json');35});3637test('simple', () => runWithFakedTimers<void>({ useFakeTimers: true }, async () => {38await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }'));39const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));40await testObject.initialize();41const config = testObject.getValue<{42foo: string;43}>();4445assert.ok(config);46assert.strictEqual(config.foo, 'bar');47}));4849test('config gets flattened', () => runWithFakedTimers<void>({ useFakeTimers: true }, async () => {50await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "testworkbench.editor.tabs": true }'));5152const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));53await testObject.initialize();54const config = testObject.getValue<{55testworkbench: {56editor: {57tabs: boolean;58};59};60}>();6162assert.ok(config);63assert.ok(config.testworkbench);64assert.ok(config.testworkbench.editor);65assert.strictEqual(config.testworkbench.editor.tabs, true);66}));6768test('error case does not explode', () => runWithFakedTimers<void>({ useFakeTimers: true }, async () => {69await fileService.writeFile(settingsResource, VSBuffer.fromString(',,,,'));7071const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));72await testObject.initialize();73const config = testObject.getValue<{74foo: string;75}>();7677assert.ok(config);78}));7980test('missing file does not explode', () => runWithFakedTimers<void>({ useFakeTimers: true }, async () => {81const testObject = disposables.add(new ConfigurationService(URI.file('__testFile'), fileService, new NullPolicyService(), new NullLogService()));82await testObject.initialize();8384const config = testObject.getValue<{ foo: string }>();8586assert.ok(config);87}));8889test('trigger configuration change event when file does not exist', () => runWithFakedTimers<void>({ useFakeTimers: true }, async () => {90const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));91await testObject.initialize();92return new Promise<void>((c, e) => {93disposables.add(Event.filter(testObject.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(() => {94assert.strictEqual(testObject.getValue('foo'), 'bar');95c();96}));97fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }')).catch(e);98});99100}));101102test('trigger configuration change event when file exists', () => runWithFakedTimers<void>({ useFakeTimers: true }, async () => {103const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));104await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }'));105await testObject.initialize();106107return new Promise<void>((c) => {108disposables.add(Event.filter(testObject.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(async (e) => {109assert.strictEqual(testObject.getValue('foo'), 'barz');110c();111}));112fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "barz" }'));113});114}));115116test('reloadConfiguration', () => runWithFakedTimers<void>({ useFakeTimers: true }, async () => {117await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }'));118119const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));120await testObject.initialize();121let config = testObject.getValue<{122foo: string;123}>();124assert.ok(config);125assert.strictEqual(config.foo, 'bar');126await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "changed" }'));127128// force a reload to get latest129await testObject.reloadConfiguration();130config = testObject.getValue<{131foo: string;132}>();133assert.ok(config);134assert.strictEqual(config.foo, 'changed');135}));136137test('model defaults', () => runWithFakedTimers<void>({ useFakeTimers: true }, async () => {138interface ITestSetting {139configuration: {140service: {141testSetting: string;142};143};144}145146const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);147configurationRegistry.registerConfiguration({148'id': '_test',149'type': 'object',150'properties': {151'configuration.service.testSetting': {152'type': 'string',153'default': 'isSet'154}155}156});157158let testObject = disposables.add(new ConfigurationService(URI.file('__testFile'), fileService, new NullPolicyService(), new NullLogService()));159await testObject.initialize();160let setting = testObject.getValue<ITestSetting>();161162assert.ok(setting);163assert.strictEqual(setting.configuration.service.testSetting, 'isSet');164165await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "testworkbench.editor.tabs": true }'));166testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));167await testObject.initialize();168169setting = testObject.getValue<ITestSetting>();170171assert.ok(setting);172assert.strictEqual(setting.configuration.service.testSetting, 'isSet');173174await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "configuration.service.testSetting": "isChanged" }'));175176await testObject.reloadConfiguration();177setting = testObject.getValue<ITestSetting>();178assert.ok(setting);179assert.strictEqual(setting.configuration.service.testSetting, 'isChanged');180}));181182test('lookup', () => runWithFakedTimers<void>({ useFakeTimers: true }, async () => {183const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);184configurationRegistry.registerConfiguration({185'id': '_test',186'type': 'object',187'properties': {188'lookup.service.testSetting': {189'type': 'string',190'default': 'isSet'191}192}193});194195const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));196await testObject.initialize();197198let res = testObject.inspect('something.missing');199assert.strictEqual(res.value, undefined);200assert.strictEqual(res.defaultValue, undefined);201assert.strictEqual(res.userValue, undefined);202assert.strictEqual(isConfigured(res), false);203204res = testObject.inspect('lookup.service.testSetting');205assert.strictEqual(res.defaultValue, 'isSet');206assert.strictEqual(res.value, 'isSet');207assert.strictEqual(res.userValue, undefined);208assert.strictEqual(isConfigured(res), false);209210await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "lookup.service.testSetting": "bar" }'));211212await testObject.reloadConfiguration();213res = testObject.inspect('lookup.service.testSetting');214assert.strictEqual(res.defaultValue, 'isSet');215assert.strictEqual(res.userValue, 'bar');216assert.strictEqual(res.value, 'bar');217assert.strictEqual(isConfigured(res), true);218219}));220221test('lookup with null', () => runWithFakedTimers<void>({ useFakeTimers: true }, async () => {222const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);223configurationRegistry.registerConfiguration({224'id': '_testNull',225'type': 'object',226'properties': {227'lookup.service.testNullSetting': {228'type': 'null',229}230}231});232233const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));234await testObject.initialize();235236let res = testObject.inspect('lookup.service.testNullSetting');237assert.strictEqual(res.defaultValue, null);238assert.strictEqual(res.value, null);239assert.strictEqual(res.userValue, undefined);240241await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "lookup.service.testNullSetting": null }'));242243await testObject.reloadConfiguration();244245res = testObject.inspect('lookup.service.testNullSetting');246assert.strictEqual(res.defaultValue, null);247assert.strictEqual(res.value, null);248assert.strictEqual(res.userValue, null);249}));250251test('update configuration', async () => {252const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);253configurationRegistry.registerConfiguration({254'id': '_test',255'type': 'object',256'properties': {257'configurationService.testSetting': {258'type': 'string',259'default': 'isSet'260}261}262});263const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));264await testObject.initialize();265266await testObject.updateValue('configurationService.testSetting', 'value');267assert.strictEqual(testObject.getValue('configurationService.testSetting'), 'value');268});269270test('update configuration when exist', async () => {271const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);272configurationRegistry.registerConfiguration({273'id': '_test',274'type': 'object',275'properties': {276'configurationService.testSetting': {277'type': 'string',278'default': 'isSet'279}280}281});282const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));283await testObject.initialize();284285await testObject.updateValue('configurationService.testSetting', 'value');286await testObject.updateValue('configurationService.testSetting', 'updatedValue');287assert.strictEqual(testObject.getValue('configurationService.testSetting'), 'updatedValue');288});289290test('update configuration to default value should remove', async () => {291const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);292configurationRegistry.registerConfiguration({293'id': '_test',294'type': 'object',295'properties': {296'configurationService.testSetting': {297'type': 'string',298'default': 'isSet'299}300}301});302const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));303await testObject.initialize();304305await testObject.updateValue('configurationService.testSetting', 'value');306await testObject.updateValue('configurationService.testSetting', 'isSet');307const inspect = testObject.inspect('configurationService.testSetting');308309assert.strictEqual(inspect.userValue, undefined);310});311312test('update configuration should remove when undefined is passed', async () => {313const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);314configurationRegistry.registerConfiguration({315'id': '_test',316'type': 'object',317'properties': {318'configurationService.testSetting': {319'type': 'string',320'default': 'isSet'321}322}323});324const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));325await testObject.initialize();326327await testObject.updateValue('configurationService.testSetting', 'value');328await testObject.updateValue('configurationService.testSetting', undefined);329const inspect = testObject.inspect('configurationService.testSetting');330331assert.strictEqual(inspect.userValue, undefined);332});333334test('update unknown configuration', async () => {335const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));336await testObject.initialize();337338await testObject.updateValue('configurationService.unknownSetting', 'value');339assert.strictEqual(testObject.getValue('configurationService.unknownSetting'), 'value');340});341342test('update configuration in non user target throws error', async () => {343const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);344configurationRegistry.registerConfiguration({345'id': '_test',346'type': 'object',347'properties': {348'configurationService.testSetting': {349'type': 'string',350'default': 'isSet'351}352}353});354const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, new NullPolicyService(), new NullLogService()));355await testObject.initialize();356357try {358await testObject.updateValue('configurationService.testSetting', 'value', ConfigurationTarget.WORKSPACE);359assert.fail('Should fail with error');360} catch (e) {361// succeess362}363});364365test('update configuration throws error for policy setting', async () => {366const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);367configurationRegistry.registerConfiguration({368'id': '_test',369'type': 'object',370'properties': {371'configurationService.policySetting': {372'type': 'string',373'default': 'isSet',374policy: {375name: 'configurationService.policySetting',376minimumVersion: '1.0.0',377}378}379}380});381382const logService = new NullLogService();383const policyFile = URI.file('policies.json');384await fileService.writeFile(policyFile, VSBuffer.fromString('{ "configurationService.policySetting": "policyValue" }'));385const policyService = disposables.add(new FilePolicyService(policyFile, fileService, logService));386const testObject = disposables.add(new ConfigurationService(settingsResource, fileService, policyService, logService));387await testObject.initialize();388389try {390await testObject.updateValue('configurationService.policySetting', 'value');391assert.fail('Should throw error');392} catch (error) {393// succeess394}395});396});397398399