mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 1b314ab317fbff7d799b21754326b7d849889ceb
This commit is contained in:
@@ -4,31 +4,37 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { IUserDataSyncStoreService, SyncResource, SyncStatus, IUserDataSyncResourceEnablementService, IRemoteUserData, ISyncData } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IUserDataSyncStoreService, SyncResource, SyncStatus, IUserDataSyncResourceEnablementService, IRemoteUserData, ISyncData, Change, USER_DATA_SYNC_SCHEME, IUserDataManifest } 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, ISyncResourcePreview } from 'vs/platform/userDataSync/common/abstractSynchronizer';
|
||||
import { AbstractSynchroniser, IResourcePreview } from 'vs/platform/userDataSync/common/abstractSynchronizer';
|
||||
import { Barrier } from 'vs/base/common/async';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
interface ITestSyncPreview extends ISyncResourcePreview {
|
||||
ref?: string;
|
||||
}
|
||||
const resource = URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'testResource', path: `/current.json` });
|
||||
|
||||
class TestSynchroniser extends AbstractSynchroniser {
|
||||
|
||||
syncBarrier: Barrier = new Barrier();
|
||||
syncResult: { hasConflicts: boolean, hasError: boolean } = { hasConflicts: false, hasError: false };
|
||||
onDoSyncCall: Emitter<void> = this._register(new Emitter<void>());
|
||||
failWhenGettingLatestRemoteUserData: boolean = false;
|
||||
|
||||
readonly resource: SyncResource = SyncResource.Settings;
|
||||
protected readonly version: number = 1;
|
||||
|
||||
private cancelled: boolean = false;
|
||||
|
||||
protected async doSync(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise<SyncStatus> {
|
||||
protected getLatestRemoteUserData(manifest: IUserDataManifest | null, lastSyncUserData: IRemoteUserData | null): Promise<IRemoteUserData> {
|
||||
if (this.failWhenGettingLatestRemoteUserData) {
|
||||
throw new Error();
|
||||
}
|
||||
return super.getLatestRemoteUserData(manifest, lastSyncUserData);
|
||||
}
|
||||
|
||||
protected async doSync(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, apply: boolean): Promise<SyncStatus> {
|
||||
this.cancelled = false;
|
||||
this.onDoSyncCall.fire();
|
||||
await this.syncBarrier.wait();
|
||||
@@ -37,39 +43,35 @@ class TestSynchroniser extends AbstractSynchroniser {
|
||||
return SyncStatus.Idle;
|
||||
}
|
||||
|
||||
return super.doSync(remoteUserData, lastSyncUserData);
|
||||
return super.doSync(remoteUserData, lastSyncUserData, apply);
|
||||
}
|
||||
|
||||
protected async generatePullPreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, token: CancellationToken): Promise<ITestSyncPreview> {
|
||||
return { hasLocalChanged: false, hasRemoteChanged: false, isLastSyncFromCurrentMachine: false, hasConflicts: this.syncResult.hasConflicts, remoteUserData, lastSyncUserData, resourcePreviews: [] };
|
||||
protected async generatePullPreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, token: CancellationToken): Promise<IResourcePreview[]> {
|
||||
return [{ localContent: null, localResource: resource, remoteContent: null, remoteResource: resource, previewContent: remoteUserData.ref, previewResource: resource, localChange: Change.Modified, remoteChange: Change.None, hasConflicts: this.syncResult.hasConflicts }];
|
||||
}
|
||||
|
||||
protected async generatePushPreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, token: CancellationToken): Promise<ITestSyncPreview> {
|
||||
return { hasLocalChanged: false, hasRemoteChanged: false, isLastSyncFromCurrentMachine: false, hasConflicts: this.syncResult.hasConflicts, remoteUserData, lastSyncUserData, resourcePreviews: [] };
|
||||
protected async generatePushPreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, token: CancellationToken): Promise<IResourcePreview[]> {
|
||||
return [{ localContent: null, localResource: resource, remoteContent: null, remoteResource: resource, previewContent: remoteUserData.ref, previewResource: resource, localChange: Change.Modified, remoteChange: Change.None, hasConflicts: this.syncResult.hasConflicts }];
|
||||
}
|
||||
|
||||
protected async generateReplacePreview(syncData: ISyncData, remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise<ITestSyncPreview> {
|
||||
return { hasLocalChanged: false, hasRemoteChanged: false, isLastSyncFromCurrentMachine: false, hasConflicts: this.syncResult.hasConflicts, remoteUserData, lastSyncUserData, resourcePreviews: [] };
|
||||
protected async generateReplacePreview(syncData: ISyncData, remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise<IResourcePreview[]> {
|
||||
return [{ localContent: null, localResource: resource, remoteContent: null, remoteResource: resource, previewContent: remoteUserData.ref, previewResource: resource, localChange: Change.Modified, remoteChange: Change.None, hasConflicts: this.syncResult.hasConflicts }];
|
||||
}
|
||||
|
||||
protected async generatePreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, token: CancellationToken): Promise<ITestSyncPreview> {
|
||||
protected async generateSyncPreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, token: CancellationToken): Promise<IResourcePreview[]> {
|
||||
if (this.syncResult.hasError) {
|
||||
throw new Error('failed');
|
||||
}
|
||||
return { ref: remoteUserData.ref, hasLocalChanged: false, hasRemoteChanged: false, isLastSyncFromCurrentMachine: false, hasConflicts: this.syncResult.hasConflicts, remoteUserData, lastSyncUserData, resourcePreviews: [] };
|
||||
return [{ localContent: null, localResource: resource, remoteContent: null, remoteResource: resource, previewContent: remoteUserData.ref, previewResource: resource, localChange: Change.Modified, remoteChange: Change.None, hasConflicts: this.syncResult.hasConflicts }];
|
||||
}
|
||||
|
||||
protected async updatePreviewWithConflict(preview: ISyncResourcePreview, conflictResource: URI, conflictContent: string): Promise<ISyncResourcePreview> {
|
||||
return preview;
|
||||
}
|
||||
|
||||
protected async applyPreview({ ref }: ITestSyncPreview, forcePush: boolean): Promise<void> {
|
||||
if (ref) {
|
||||
await this.apply(ref);
|
||||
protected async applyPreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, preview: IResourcePreview[], forcePush: boolean): Promise<void> {
|
||||
if (preview[0]?.previewContent) {
|
||||
await this.applyRef(preview[0].previewContent);
|
||||
}
|
||||
}
|
||||
|
||||
async apply(ref: string): Promise<void> {
|
||||
async applyRef(ref: string): Promise<void> {
|
||||
const remoteUserData = await this.updateRemoteUserData('', ref);
|
||||
await this.updateLastSyncUserData(remoteUserData);
|
||||
}
|
||||
@@ -137,19 +139,6 @@ suite('TestSynchronizer', () => {
|
||||
assert.deepEqual(testObject.status, SyncStatus.Idle);
|
||||
});
|
||||
|
||||
test('status is set correctly when sync has conflicts', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
testObject.syncResult = { hasConflicts: true, hasError: false };
|
||||
testObject.syncBarrier.open();
|
||||
|
||||
const actual: SyncStatus[] = [];
|
||||
disposableStore.add(testObject.onDidChangeStatus(status => actual.push(status)));
|
||||
await testObject.sync(await client.manifest());
|
||||
|
||||
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, SyncResource.Settings);
|
||||
testObject.syncResult = { hasError: true, hasConflicts: false };
|
||||
@@ -167,6 +156,17 @@ suite('TestSynchronizer', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('status is set to hasConflicts when asked to sync if there are conflicts', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
testObject.syncResult = { hasConflicts: true, hasError: false };
|
||||
testObject.syncBarrier.open();
|
||||
|
||||
await testObject.sync(await client.manifest());
|
||||
|
||||
assert.deepEqual(testObject.status, SyncStatus.HasConflicts);
|
||||
assertConflicts(testObject.conflicts, [resource]);
|
||||
});
|
||||
|
||||
test('sync should not run if syncing already', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
const promise = Event.toPromise(testObject.onDoSyncCall.event);
|
||||
@@ -181,7 +181,7 @@ suite('TestSynchronizer', () => {
|
||||
assert.deepEqual(actual, []);
|
||||
assert.deepEqual(testObject.status, SyncStatus.Syncing);
|
||||
|
||||
testObject.stop();
|
||||
await testObject.stop();
|
||||
});
|
||||
|
||||
test('sync should not run if disabled', async () => {
|
||||
@@ -221,7 +221,7 @@ suite('TestSynchronizer', () => {
|
||||
// update remote data before syncing so that 412 is thrown by server
|
||||
const disposable = testObject.onDoSyncCall.event(async () => {
|
||||
disposable.dispose();
|
||||
await testObject.apply(ref);
|
||||
await testObject.applyRef(ref);
|
||||
server.reset();
|
||||
testObject.syncBarrier.open();
|
||||
});
|
||||
@@ -251,5 +251,115 @@ suite('TestSynchronizer', () => {
|
||||
assert.deepEqual(server.requests, []);
|
||||
});
|
||||
|
||||
test('status is reset when getting latest remote data fails', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
testObject.failWhenGettingLatestRemoteUserData = true;
|
||||
|
||||
try {
|
||||
await testObject.sync(await client.manifest());
|
||||
assert.fail('Should throw an error');
|
||||
} catch (error) {
|
||||
}
|
||||
|
||||
assert.equal(testObject.status, SyncStatus.Idle);
|
||||
});
|
||||
|
||||
test('preview: status is set to syncing when asked for preview if there are no conflicts', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
testObject.syncResult = { hasConflicts: false, hasError: false };
|
||||
testObject.syncBarrier.open();
|
||||
|
||||
const preview = await testObject.preview(await client.manifest());
|
||||
|
||||
assert.deepEqual(testObject.status, SyncStatus.Syncing);
|
||||
assertPreviews(preview!.resourcePreviews, [resource]);
|
||||
assertConflicts(testObject.conflicts, []);
|
||||
});
|
||||
|
||||
test('preview: status is set to idle after merging if there are no conflicts', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
testObject.syncResult = { hasConflicts: false, hasError: false };
|
||||
testObject.syncBarrier.open();
|
||||
|
||||
let preview = await testObject.preview(await client.manifest());
|
||||
preview = await testObject.merge(preview!.resourcePreviews[0].previewResource, false);
|
||||
|
||||
assert.deepEqual(testObject.status, SyncStatus.Idle);
|
||||
assert.equal(preview, null);
|
||||
assertConflicts(testObject.conflicts, []);
|
||||
});
|
||||
|
||||
test('preview: status is set to idle and sync is applied after accepting when there are no conflicts before merging', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
testObject.syncResult = { hasConflicts: false, hasError: false };
|
||||
testObject.syncBarrier.open();
|
||||
|
||||
let preview = await testObject.preview(await client.manifest());
|
||||
preview = await testObject.acceptPreviewContent(preview!.resourcePreviews[0].previewResource, preview!.resourcePreviews[0].previewContent!, false);
|
||||
|
||||
assert.deepEqual(testObject.status, SyncStatus.Idle);
|
||||
assert.equal(preview, null);
|
||||
assertConflicts(testObject.conflicts, []);
|
||||
});
|
||||
|
||||
test('preview: status is set to syncing when asked for preview if there are conflicts', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
testObject.syncResult = { hasConflicts: true, hasError: false };
|
||||
testObject.syncBarrier.open();
|
||||
|
||||
const preview = await testObject.preview(await client.manifest());
|
||||
|
||||
assert.deepEqual(testObject.status, SyncStatus.Syncing);
|
||||
assertPreviews(preview!.resourcePreviews, [resource]);
|
||||
assertConflicts(testObject.conflicts, []);
|
||||
});
|
||||
|
||||
test('preview: status is set to hasConflicts after merging', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
testObject.syncResult = { hasConflicts: true, hasError: false };
|
||||
testObject.syncBarrier.open();
|
||||
|
||||
const preview = await testObject.preview(await client.manifest());
|
||||
await testObject.merge(preview!.resourcePreviews[0].previewResource, false);
|
||||
|
||||
assert.deepEqual(testObject.status, SyncStatus.HasConflicts);
|
||||
assertPreviews(preview!.resourcePreviews, [resource]);
|
||||
assertConflicts(testObject.conflicts, [preview!.resourcePreviews[0].previewResource]);
|
||||
});
|
||||
|
||||
test('preview: status is set to idle and sync is applied after accepting when there are conflicts', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
testObject.syncResult = { hasConflicts: true, hasError: false };
|
||||
testObject.syncBarrier.open();
|
||||
|
||||
let preview = await testObject.preview(await client.manifest());
|
||||
await testObject.merge(preview!.resourcePreviews[0].previewResource, false);
|
||||
preview = await testObject.acceptPreviewContent(preview!.resourcePreviews[0].previewResource, preview!.resourcePreviews[0].previewContent!, false);
|
||||
|
||||
assert.deepEqual(testObject.status, SyncStatus.Idle);
|
||||
assert.equal(preview, null);
|
||||
assertConflicts(testObject.conflicts, []);
|
||||
});
|
||||
|
||||
test('preview: status is set to idle and sync is applied after accepting when there are conflicts before merging', async () => {
|
||||
const testObject: TestSynchroniser = client.instantiationService.createInstance(TestSynchroniser, SyncResource.Settings);
|
||||
testObject.syncResult = { hasConflicts: true, hasError: false };
|
||||
testObject.syncBarrier.open();
|
||||
|
||||
let preview = await testObject.preview(await client.manifest());
|
||||
preview = await testObject.acceptPreviewContent(preview!.resourcePreviews[0].previewResource, preview!.resourcePreviews[0].previewContent!, false);
|
||||
|
||||
assert.deepEqual(testObject.status, SyncStatus.Idle);
|
||||
assert.equal(preview, null);
|
||||
assertConflicts(testObject.conflicts, []);
|
||||
});
|
||||
|
||||
function assertConflicts(actual: IResourcePreview[], expected: URI[]) {
|
||||
assert.deepEqual(actual.map(({ previewResource }) => previewResource.toString()), expected.map(uri => uri.toString()));
|
||||
}
|
||||
|
||||
function assertPreviews(actual: IResourcePreview[], expected: URI[]) {
|
||||
assert.deepEqual(actual.map(({ previewResource }) => previewResource.toString()), expected.map(uri => uri.toString()));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user