Merge from vscode cfc1ab4c5f816765b91fb7ead3c3427a7c8581a3

This commit is contained in:
ADS Merger
2020-03-11 04:19:23 +00:00
parent 16fab722d5
commit 4c3e48773d
880 changed files with 20441 additions and 11232 deletions

View File

@@ -0,0 +1,200 @@
/*---------------------------------------------------------------------------------------------
* 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 { ResourceKey, IUserDataSyncStoreService, SyncSource, SyncStatus, IUserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncClient, UserDataSyncTestServer } from 'vs/platform/userDataSync/test/common/userDataSyncClient';
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { AbstractSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
import { Barrier } from 'vs/base/common/async';
import { Emitter, Event } from 'vs/base/common/event';
class TestSynchroniser extends AbstractSynchroniser {
syncBarrier: Barrier = new Barrier();
syncResult: { status?: SyncStatus, error?: boolean } = {};
onDoSyncCall: Emitter<void> = this._register(new Emitter<void>());
readonly resourceKey: ResourceKey = 'settings';
protected readonly version: number = 1;
private cancelled: boolean = false;
protected async performSync(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise<SyncStatus> {
this.cancelled = false;
this.onDoSyncCall.fire();
await this.syncBarrier.wait();
if (this.cancelled) {
return SyncStatus.Idle;
}
if (this.syncResult.error) {
throw new Error('failed');
}
await this.apply(remoteUserData.ref);
return this.syncResult.status || SyncStatus.Idle;
}
async apply(ref: string): Promise<void> {
ref = await this.userDataSyncStoreService.write(this.resourceKey, '', ref);
await this.updateLastSyncUserData({ ref, syncData: { content: '', version: this.version } });
}
stop(): void {
this.cancelled = true;
this.syncBarrier.open();
}
}
suite('TestSynchronizer', () => {
const disposableStore = new DisposableStore();
const server = new UserDataSyncTestServer();
let client: UserDataSyncClient;
let userDataSyncStoreService: IUserDataSyncStoreService;
setup(async () => {
client = disposableStore.add(new UserDataSyncClient(server));
await client.setUp();
userDataSyncStoreService = client.instantiationService.get(IUserDataSyncStoreService);
disposableStore.add(toDisposable(() => userDataSyncStoreService.clear()));
});
teardown(() => disposableStore.clear());
test('status is syncing', async () => {
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncSource.Settings, 'settings');
const actual: SyncStatus[] = [];
disposableStore.add(testObject.onDidChangeStatus(status => actual.push(status)));
const promise = Event.toPromise(testObject.onDoSyncCall.event);
testObject.sync();
await promise;
assert.deepEqual(actual, [SyncStatus.Syncing]);
assert.deepEqual(testObject.status, SyncStatus.Syncing);
testObject.stop();
});
test('status is set correctly when sync is finished', async () => {
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncSource.Settings, 'settings');
testObject.syncBarrier.open();
const actual: SyncStatus[] = [];
disposableStore.add(testObject.onDidChangeStatus(status => actual.push(status)));
await testObject.sync();
assert.deepEqual(actual, [SyncStatus.Syncing, SyncStatus.Idle]);
assert.deepEqual(testObject.status, SyncStatus.Idle);
});
test('status is set correctly when sync has conflicts', async () => {
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncSource.Settings, 'settings');
testObject.syncResult = { status: SyncStatus.HasConflicts };
testObject.syncBarrier.open();
const actual: SyncStatus[] = [];
disposableStore.add(testObject.onDidChangeStatus(status => actual.push(status)));
await testObject.sync();
assert.deepEqual(actual, [SyncStatus.Syncing, SyncStatus.HasConflicts]);
assert.deepEqual(testObject.status, SyncStatus.HasConflicts);
});
test('status is set correctly when sync has errors', async () => {
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncSource.Settings, 'settings');
testObject.syncResult = { error: true };
testObject.syncBarrier.open();
const actual: SyncStatus[] = [];
disposableStore.add(testObject.onDidChangeStatus(status => actual.push(status)));
try {
await testObject.sync();
assert.fail('Should fail');
} catch (e) {
assert.deepEqual(actual, [SyncStatus.Syncing, SyncStatus.Idle]);
assert.deepEqual(testObject.status, SyncStatus.Idle);
}
});
test('sync should not run if syncing already', async () => {
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncSource.Settings, 'settings');
const promise = Event.toPromise(testObject.onDoSyncCall.event);
testObject.sync();
await promise;
const actual: SyncStatus[] = [];
disposableStore.add(testObject.onDidChangeStatus(status => actual.push(status)));
await testObject.sync();
assert.deepEqual(actual, []);
assert.deepEqual(testObject.status, SyncStatus.Syncing);
testObject.stop();
});
test('sync should not run if disabled', async () => {
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncSource.Settings, 'settings');
client.instantiationService.get(IUserDataSyncEnablementService).setResourceEnablement(testObject.resourceKey, false);
const actual: SyncStatus[] = [];
disposableStore.add(testObject.onDidChangeStatus(status => actual.push(status)));
await testObject.sync();
assert.deepEqual(actual, []);
assert.deepEqual(testObject.status, SyncStatus.Idle);
});
test('sync should not run if there are conflicts', async () => {
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncSource.Settings, 'settings');
testObject.syncResult = { status: SyncStatus.HasConflicts };
testObject.syncBarrier.open();
await testObject.sync();
const actual: SyncStatus[] = [];
disposableStore.add(testObject.onDidChangeStatus(status => actual.push(status)));
await testObject.sync();
assert.deepEqual(actual, []);
assert.deepEqual(testObject.status, SyncStatus.HasConflicts);
});
test('request latest data on precondition failure', async () => {
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncSource.Settings, 'settings');
// Sync once
testObject.syncBarrier.open();
await testObject.sync();
testObject.syncBarrier = new Barrier();
// update remote data before syncing so that 412 is thrown by server
const disposable = testObject.onDoSyncCall.event(async () => {
disposable.dispose();
await testObject.apply(ref);
server.reset();
testObject.syncBarrier.open();
});
// Start sycing
const { ref } = await userDataSyncStoreService.read(testObject.resourceKey, null);
await testObject.sync(ref);
assert.deepEqual(server.requests, [
{ type: 'POST', url: `${server.url}/v1/resource/${testObject.resourceKey}`, headers: { 'If-Match': ref } },
{ type: 'GET', url: `${server.url}/v1/resource/${testObject.resourceKey}/latest`, headers: {} },
{ type: 'POST', url: `${server.url}/v1/resource/${testObject.resourceKey}`, headers: { 'If-Match': `${parseInt(ref) + 1}` } },
]);
});
});