mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-07 09:35:41 -05:00
405 lines
16 KiB
TypeScript
405 lines
16 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import * as assert from 'assert';
|
|
import { UserDataSyncClient, UserDataSyncTestServer } from 'vs/platform/userDataSync/test/common/userDataSyncClient';
|
|
import { DisposableStore } from 'vs/base/common/lifecycle';
|
|
import { UserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataAutoSyncService';
|
|
import { IUserDataSyncService, SyncResource, UserDataAutoSyncError, UserDataSyncErrorCode, UserDataSyncStoreError } from 'vs/platform/userDataSync/common/userDataSync';
|
|
import { Event } from 'vs/base/common/event';
|
|
import { IFileService } from 'vs/platform/files/common/files';
|
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
|
import { VSBuffer } from 'vs/base/common/buffer';
|
|
import { joinPath } from 'vs/base/common/resources';
|
|
import { IUserDataSyncMachinesService } from 'vs/platform/userDataSync/common/userDataSyncMachines';
|
|
|
|
class TestUserDataAutoSyncService extends UserDataAutoSyncService {
|
|
protected startAutoSync(): boolean { return false; }
|
|
protected getSyncTriggerDelayTime(): number { return 50; }
|
|
|
|
sync(): Promise<void> {
|
|
return this.triggerSync(['sync'], false);
|
|
}
|
|
}
|
|
|
|
suite('UserDataAutoSyncService', () => {
|
|
|
|
const disposableStore = new DisposableStore();
|
|
|
|
teardown(() => disposableStore.clear());
|
|
|
|
test('test auto sync with sync resource change triggers sync', async () => {
|
|
// Setup the client
|
|
const target = new UserDataSyncTestServer();
|
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
|
await client.setUp();
|
|
|
|
// Sync once and reset requests
|
|
await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run();
|
|
target.reset();
|
|
|
|
const testObject: UserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
|
|
// Trigger auto sync with settings change
|
|
await testObject.triggerSync([SyncResource.Settings], false);
|
|
|
|
// Filter out machine requests
|
|
const actual = target.requests.filter(request => !request.url.startsWith(`${target.url}/v1/resource/machines`));
|
|
|
|
// Make sure only one manifest request is made
|
|
assert.deepEqual(actual, [{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} }]);
|
|
});
|
|
|
|
test('test auto sync with sync resource change triggers sync for every change', async () => {
|
|
// Setup the client
|
|
const target = new UserDataSyncTestServer();
|
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
|
await client.setUp();
|
|
|
|
// Sync once and reset requests
|
|
await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run();
|
|
target.reset();
|
|
|
|
const testObject: UserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
|
|
// Trigger auto sync with settings change multiple times
|
|
for (let counter = 0; counter < 2; counter++) {
|
|
await testObject.triggerSync([SyncResource.Settings], false);
|
|
}
|
|
|
|
// Filter out machine requests
|
|
const actual = target.requests.filter(request => !request.url.startsWith(`${target.url}/v1/resource/machines`));
|
|
|
|
assert.deepEqual(actual, [
|
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} }
|
|
]);
|
|
});
|
|
|
|
test('test auto sync with non sync resource change triggers sync', async () => {
|
|
// Setup the client
|
|
const target = new UserDataSyncTestServer();
|
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
|
await client.setUp();
|
|
|
|
// Sync once and reset requests
|
|
await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run();
|
|
target.reset();
|
|
|
|
const testObject: UserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
|
|
// Trigger auto sync with window focus once
|
|
await testObject.triggerSync(['windowFocus'], true);
|
|
|
|
// Filter out machine requests
|
|
const actual = target.requests.filter(request => !request.url.startsWith(`${target.url}/v1/resource/machines`));
|
|
|
|
// Make sure only one manifest request is made
|
|
assert.deepEqual(actual, [{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} }]);
|
|
});
|
|
|
|
test('test auto sync with non sync resource change does not trigger continuous syncs', async () => {
|
|
// Setup the client
|
|
const target = new UserDataSyncTestServer();
|
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
|
await client.setUp();
|
|
|
|
// Sync once and reset requests
|
|
await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run();
|
|
target.reset();
|
|
|
|
const testObject: UserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
|
|
// Trigger auto sync with window focus multiple times
|
|
for (let counter = 0; counter < 2; counter++) {
|
|
await testObject.triggerSync(['windowFocus'], true);
|
|
}
|
|
|
|
// Filter out machine requests
|
|
const actual = target.requests.filter(request => !request.url.startsWith(`${target.url}/v1/resource/machines`));
|
|
|
|
// Make sure only one manifest request is made
|
|
assert.deepEqual(actual, [{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} }]);
|
|
});
|
|
|
|
test('test first auto sync requests', async () => {
|
|
// Setup the client
|
|
const target = new UserDataSyncTestServer();
|
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
|
await client.setUp();
|
|
const testObject: TestUserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
|
|
await testObject.sync();
|
|
|
|
assert.deepEqual(target.requests, [
|
|
// Manifest
|
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
|
// Machines
|
|
{ type: 'GET', url: `${target.url}/v1/resource/machines/latest`, headers: {} },
|
|
// Settings
|
|
{ type: 'GET', url: `${target.url}/v1/resource/settings/latest`, headers: {} },
|
|
{ type: 'POST', url: `${target.url}/v1/resource/settings`, headers: { 'If-Match': '0' } },
|
|
// Keybindings
|
|
{ type: 'GET', url: `${target.url}/v1/resource/keybindings/latest`, headers: {} },
|
|
{ type: 'POST', url: `${target.url}/v1/resource/keybindings`, headers: { 'If-Match': '0' } },
|
|
// Snippets
|
|
{ type: 'GET', url: `${target.url}/v1/resource/snippets/latest`, headers: {} },
|
|
{ type: 'POST', url: `${target.url}/v1/resource/snippets`, headers: { 'If-Match': '0' } },
|
|
// Global state
|
|
{ type: 'GET', url: `${target.url}/v1/resource/globalState/latest`, headers: {} },
|
|
{ type: 'POST', url: `${target.url}/v1/resource/globalState`, headers: { 'If-Match': '0' } },
|
|
// Extensions
|
|
{ type: 'GET', url: `${target.url}/v1/resource/extensions/latest`, headers: {} },
|
|
// Manifest
|
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
|
// Machines
|
|
{ type: 'POST', url: `${target.url}/v1/resource/machines`, headers: { 'If-Match': '0' } }
|
|
]);
|
|
|
|
});
|
|
|
|
test('test further auto sync requests without changes', async () => {
|
|
// Setup the client
|
|
const target = new UserDataSyncTestServer();
|
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
|
await client.setUp();
|
|
const testObject: TestUserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
|
|
// Sync once and reset requests
|
|
await testObject.sync();
|
|
target.reset();
|
|
|
|
await testObject.sync();
|
|
|
|
assert.deepEqual(target.requests, [
|
|
// Manifest
|
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} }
|
|
]);
|
|
|
|
});
|
|
|
|
test('test further auto sync requests with changes', async () => {
|
|
// Setup the client
|
|
const target = new UserDataSyncTestServer();
|
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
|
await client.setUp();
|
|
const testObject: TestUserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
|
|
// Sync once and reset requests
|
|
await testObject.sync();
|
|
target.reset();
|
|
|
|
// Do changes in the client
|
|
const fileService = client.instantiationService.get(IFileService);
|
|
const environmentService = client.instantiationService.get(IEnvironmentService);
|
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 14 })));
|
|
await fileService.writeFile(environmentService.keybindingsResource, VSBuffer.fromString(JSON.stringify([{ 'command': 'abcd', 'key': 'cmd+c' }])));
|
|
await fileService.writeFile(joinPath(environmentService.snippetsHome, 'html.json'), VSBuffer.fromString(`{}`));
|
|
await fileService.writeFile(environmentService.argvResource, VSBuffer.fromString(JSON.stringify({ 'locale': 'de' })));
|
|
await testObject.sync();
|
|
|
|
assert.deepEqual(target.requests, [
|
|
// Manifest
|
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
|
// Settings
|
|
{ type: 'POST', url: `${target.url}/v1/resource/settings`, headers: { 'If-Match': '1' } },
|
|
// Keybindings
|
|
{ type: 'POST', url: `${target.url}/v1/resource/keybindings`, headers: { 'If-Match': '1' } },
|
|
// Snippets
|
|
{ type: 'POST', url: `${target.url}/v1/resource/snippets`, headers: { 'If-Match': '1' } },
|
|
// Global state
|
|
{ type: 'POST', url: `${target.url}/v1/resource/globalState`, headers: { 'If-Match': '1' } },
|
|
]);
|
|
|
|
});
|
|
|
|
test('test auto sync send execution id header', async () => {
|
|
// Setup the client
|
|
const target = new UserDataSyncTestServer();
|
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
|
await client.setUp();
|
|
const testObject: TestUserDataAutoSyncService = client.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
|
|
// Sync once and reset requests
|
|
await testObject.sync();
|
|
target.reset();
|
|
|
|
await testObject.sync();
|
|
|
|
for (const request of target.requestsWithAllHeaders) {
|
|
const hasExecutionIdHeader = request.headers && request.headers['X-Execution-Id'] && request.headers['X-Execution-Id'].length > 0;
|
|
if (request.url.startsWith(`${target.url}/v1/resource/machines`)) {
|
|
assert.ok(!hasExecutionIdHeader, `Should not have execution header: ${request.url}`);
|
|
} else {
|
|
assert.ok(hasExecutionIdHeader, `Should have execution header: ${request.url}`);
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
test('test delete on one client throws turned off error on other client while syncing', async () => {
|
|
const target = new UserDataSyncTestServer();
|
|
|
|
// Set up and sync from the client
|
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
|
await client.setUp();
|
|
await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run();
|
|
|
|
// Set up and sync from the test client
|
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
|
await testClient.setUp();
|
|
const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
await testObject.sync();
|
|
|
|
// Reset from the first client
|
|
await client.instantiationService.get(IUserDataSyncService).reset();
|
|
|
|
// Sync from the test client
|
|
target.reset();
|
|
|
|
const errorPromise = Event.toPromise(testObject.onError);
|
|
await testObject.sync();
|
|
|
|
const e = await errorPromise;
|
|
assert.ok(e instanceof UserDataAutoSyncError);
|
|
assert.deepEqual((<UserDataAutoSyncError>e).code, UserDataSyncErrorCode.TurnedOff);
|
|
assert.deepEqual(target.requests, [
|
|
// Manifest
|
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
|
// Machine
|
|
{ type: 'GET', url: `${target.url}/v1/resource/machines/latest`, headers: { 'If-None-Match': '1' } },
|
|
]);
|
|
});
|
|
|
|
test('test disabling the machine turns off sync', async () => {
|
|
const target = new UserDataSyncTestServer();
|
|
|
|
// Set up and sync from the test client
|
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
|
await testClient.setUp();
|
|
const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
await testObject.sync();
|
|
|
|
// Disable current machine
|
|
const userDataSyncMachinesService = testClient.instantiationService.get(IUserDataSyncMachinesService);
|
|
const machines = await userDataSyncMachinesService.getMachines();
|
|
const currentMachine = machines.find(m => m.isCurrent)!;
|
|
await userDataSyncMachinesService.setEnablement(currentMachine.id, false);
|
|
|
|
target.reset();
|
|
|
|
const errorPromise = Event.toPromise(testObject.onError);
|
|
await testObject.sync();
|
|
|
|
const e = await errorPromise;
|
|
assert.ok(e instanceof UserDataAutoSyncError);
|
|
assert.deepEqual((<UserDataAutoSyncError>e).code, UserDataSyncErrorCode.TurnedOff);
|
|
assert.deepEqual(target.requests, [
|
|
// Manifest
|
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
|
// Machine
|
|
{ type: 'GET', url: `${target.url}/v1/resource/machines/latest`, headers: { 'If-None-Match': '2' } },
|
|
{ type: 'POST', url: `${target.url}/v1/resource/machines`, headers: { 'If-Match': '2' } },
|
|
]);
|
|
});
|
|
|
|
test('test removing the machine adds machine back', async () => {
|
|
const target = new UserDataSyncTestServer();
|
|
|
|
// Set up and sync from the test client
|
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
|
await testClient.setUp();
|
|
const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
await testObject.sync();
|
|
|
|
// Remove current machine
|
|
await testClient.instantiationService.get(IUserDataSyncMachinesService).removeCurrentMachine();
|
|
|
|
target.reset();
|
|
|
|
await testObject.sync();
|
|
assert.deepEqual(target.requests, [
|
|
// Manifest
|
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
|
// Machine
|
|
{ type: 'POST', url: `${target.url}/v1/resource/machines`, headers: { 'If-Match': '2' } },
|
|
]);
|
|
});
|
|
|
|
test('test creating new session from one client throws session expired error on another client while syncing', async () => {
|
|
const target = new UserDataSyncTestServer();
|
|
|
|
// Set up and sync from the client
|
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
|
await client.setUp();
|
|
await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run();
|
|
|
|
// Set up and sync from the test client
|
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
|
await testClient.setUp();
|
|
const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
await testObject.sync();
|
|
|
|
// Reset from the first client
|
|
await client.instantiationService.get(IUserDataSyncService).reset();
|
|
|
|
// Sync again from the first client to create new session
|
|
await (await client.instantiationService.get(IUserDataSyncService).createSyncTask()).run();
|
|
|
|
// Sync from the test client
|
|
target.reset();
|
|
|
|
const errorPromise = Event.toPromise(testObject.onError);
|
|
await testObject.sync();
|
|
|
|
const e = await errorPromise;
|
|
assert.ok(e instanceof UserDataAutoSyncError);
|
|
assert.deepEqual((<UserDataAutoSyncError>e).code, UserDataSyncErrorCode.SessionExpired);
|
|
assert.deepEqual(target.requests, [
|
|
// Manifest
|
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
|
// Machine
|
|
{ type: 'GET', url: `${target.url}/v1/resource/machines/latest`, headers: { 'If-None-Match': '1' } },
|
|
]);
|
|
});
|
|
|
|
test('test rate limit on server', async () => {
|
|
const target = new UserDataSyncTestServer(5);
|
|
|
|
// Set up and sync from the test client
|
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
|
await testClient.setUp();
|
|
const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
|
|
const errorPromise = Event.toPromise(testObject.onError);
|
|
while (target.requests.length < 5) {
|
|
await testObject.sync();
|
|
}
|
|
|
|
const e = await errorPromise;
|
|
assert.ok(e instanceof UserDataSyncStoreError);
|
|
assert.deepEqual((<UserDataSyncStoreError>e).code, UserDataSyncErrorCode.TooManyRequests);
|
|
});
|
|
|
|
test('test auto sync is suspended when server donot accepts requests', async () => {
|
|
const target = new UserDataSyncTestServer(5, 1);
|
|
|
|
// Set up and sync from the test client
|
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
|
await testClient.setUp();
|
|
const testObject: TestUserDataAutoSyncService = testClient.instantiationService.createInstance(TestUserDataAutoSyncService);
|
|
|
|
while (target.requests.length < 5) {
|
|
await testObject.sync();
|
|
}
|
|
|
|
target.reset();
|
|
await testObject.sync();
|
|
|
|
assert.deepEqual(target.requests, []);
|
|
});
|
|
|
|
});
|