From d7ce91be575dc4f87bd48939081a2422a222d5c2 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 9 Dec 2019 20:01:32 +0100 Subject: [PATCH] #86401 add merge tests --- .../userDataSync/common/extensionsMerge.ts | 10 +- .../test/common/extensionsMerge.test.ts | 412 +++++++++++++++++- 2 files changed, 416 insertions(+), 6 deletions(-) diff --git a/src/vs/platform/userDataSync/common/extensionsMerge.ts b/src/vs/platform/userDataSync/common/extensionsMerge.ts index ce4a95ea624..364c7513ecd 100644 --- a/src/vs/platform/userDataSync/common/extensionsMerge.ts +++ b/src/vs/platform/userDataSync/common/extensionsMerge.ts @@ -59,8 +59,8 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync return { added: [], removed: [], updated: [], remote: null }; } - const baseToLocal = lastSyncExtensionsMap ? compare(lastSyncExtensionsMap, localExtensionsMap, ignoredExtensionsSet) : { added: keys(localExtensionsMap).reduce((r, k) => { r.add(k); return r; }, new Set()), removed: new Set(), updated: new Set() }; - const baseToRemote = lastSyncExtensionsMap ? compare(lastSyncExtensionsMap, remoteExtensionsMap, ignoredExtensionsSet) : { added: keys(remoteExtensionsMap).reduce((r, k) => { r.add(k); return r; }, new Set()), removed: new Set(), updated: new Set() }; + const baseToLocal = compare(lastSyncExtensionsMap, localExtensionsMap, ignoredExtensionsSet); + const baseToRemote = compare(lastSyncExtensionsMap, remoteExtensionsMap, ignoredExtensionsSet); const massageSyncExtension = (extension: ISyncExtension, key: string): ISyncExtension => { const massagedExtension: ISyncExtension = { @@ -144,8 +144,8 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync return { added, removed, updated, remote }; } -function compare(from: Map, to: Map, ignoredExtensions: Set): { added: Set, removed: Set, updated: Set } { - const fromKeys = keys(from).filter(key => !ignoredExtensions.has(key)); +function compare(from: Map | null, to: Map, ignoredExtensions: Set): { added: Set, removed: Set, updated: Set } { + const fromKeys = from ? keys(from).filter(key => !ignoredExtensions.has(key)) : []; const toKeys = keys(to).filter(key => !ignoredExtensions.has(key)); const added = toKeys.filter(key => fromKeys.indexOf(key) === -1).reduce((r, key) => { r.add(key); return r; }, new Set()); const removed = fromKeys.filter(key => toKeys.indexOf(key) === -1).reduce((r, key) => { r.add(key); return r; }, new Set()); @@ -155,7 +155,7 @@ function compare(from: Map, to: Map { assert.deepEqual(actual.remote, expected); }); + test('merge returns local extension if remote does not exist with skipped extensions', async () => { + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const skippedExtension: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + ]; + const expected: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, null, null, skippedExtension, []); + + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, expected); + }); + + test('merge returns local extension if remote does not exist with skipped and ignored extensions', async () => { + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const skippedExtension: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + ]; + const expected: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, null, null, skippedExtension, ['a']); + + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, expected); + }); + test('merge local and remote extensions when there is no base', async () => { const localExtensions: ISyncExtension[] = [ { identifier: { id: 'a', uuid: 'a' }, enabled: true }, @@ -78,9 +123,374 @@ suite('ExtensionsMerge - No Conflicts', () => { { identifier: { id: 'd', uuid: 'd' }, enabled: true }, ]; - const actual = merge(localExtensions, remoteExtensions, null, [], ['A']); + const actual = merge(localExtensions, remoteExtensions, null, [], []); + + assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' }, enabled: true }, { identifier: { id: 'c', uuid: 'c' }, enabled: true }]); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, expected); + }); + + test('merge local and remote extensions when there is no base and with ignored extensions', async () => { + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const expected: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, null, [], ['a']); + + assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' }, enabled: true }, { identifier: { id: 'c', uuid: 'c' }, enabled: true }]); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, expected); + }); + + test('merge local and remote extensions when remote is moved forwarded', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []); assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' }, enabled: true }, { identifier: { id: 'c', uuid: 'c' }, enabled: true }]); + assert.deepEqual(actual.removed, [{ id: 'a', uuid: 'a' }, { id: 'd', uuid: 'd' }]); + assert.deepEqual(actual.updated, []); + assert.equal(actual.remote, null); + }); + + test('merge local and remote extensions when remote moved forwarded with ignored extensions', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['a']); + + assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' }, enabled: true }, { identifier: { id: 'c', uuid: 'c' }, enabled: true }]); + assert.deepEqual(actual.removed, [{ id: 'd', uuid: 'd' }]); + assert.deepEqual(actual.updated, []); + assert.equal(actual.remote, null); + }); + + test('merge local and remote extensions when remote is moved forwarded with skipped extensions', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const skippedExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, []); + + assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' }, enabled: true }, { identifier: { id: 'c', uuid: 'c' }, enabled: true }]); + assert.deepEqual(actual.removed, [{ id: 'd', uuid: 'd' }]); + assert.deepEqual(actual.updated, []); + assert.equal(actual.remote, null); + }); + + test('merge local and remote extensions when remote is moved forwarded with skipped and ignored extensions', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const skippedExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['b']); + + assert.deepEqual(actual.added, [{ identifier: { id: 'c', uuid: 'c' }, enabled: true }]); + assert.deepEqual(actual.removed, [{ id: 'd', uuid: 'd' }]); + assert.deepEqual(actual.updated, []); + assert.equal(actual.remote, null); + }); + + test('merge local and remote extensions when local is moved forwarded', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []); + + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, localExtensions); + }); + + test('merge local and remote extensions when local is moved forwarded with ignored settings', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['b']); + + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, [ + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]); + }); + + test('merge local and remote extensions when local is moved forwarded with skipped extensions', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const skippedExtensions: ISyncExtension[] = [ + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const expected: ISyncExtension[] = [ + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, []); + + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, expected); + }); + + test('merge local and remote extensions when local is moved forwarded with skipped and ignored extensions', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const skippedExtensions: ISyncExtension[] = [ + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const expected: ISyncExtension[] = [ + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['c']); + + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, expected); + }); + + test('merge local and remote extensions when both moved forwarded', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'e', uuid: 'e' }, enabled: true }, + ]; + const expected: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'e', uuid: 'e' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []); + + assert.deepEqual(actual.added, [{ identifier: { id: 'e', uuid: 'e' }, enabled: true }]); + assert.deepEqual(actual.removed, [{ id: 'a', uuid: 'a' }]); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, expected); + }); + + test('merge local and remote extensions when both moved forwarded with ignored extensions', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'e', uuid: 'e' }, enabled: true }, + ]; + const expected: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'e', uuid: 'e' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['a', 'e']); + + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, expected); + }); + + test('merge local and remote extensions when both moved forwarded with skipped extensions', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const skippedExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'e', uuid: 'e' }, enabled: true }, + ]; + const expected: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'e', uuid: 'e' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, []); + + assert.deepEqual(actual.added, [{ identifier: { id: 'e', uuid: 'e' }, enabled: true }]); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, expected); + }); + + test('merge local and remote extensions when both moved forwarded with skipped and ignoredextensions', async () => { + const baseExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const skippedExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + ]; + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'e', uuid: 'e' }, enabled: true }, + ]; + const expected: ISyncExtension[] = [ + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'e', uuid: 'e' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['e']); + + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.updated, []); + assert.deepEqual(actual.remote, expected); + }); + + test('merge when remote extension has no uuid and different extension id case', async () => { + const localExtensions: ISyncExtension[] = [ + { identifier: { id: 'a', uuid: 'a' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + const remoteExtensions: ISyncExtension[] = [ + { identifier: { id: 'A' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + ]; + const expected: ISyncExtension[] = [ + { identifier: { id: 'A' }, enabled: true }, + { identifier: { id: 'd', uuid: 'd' }, enabled: true }, + { identifier: { id: 'b', uuid: 'b' }, enabled: true }, + { identifier: { id: 'c', uuid: 'c' }, enabled: true }, + ]; + + const actual = merge(localExtensions, remoteExtensions, null, [], []); + + assert.deepEqual(actual.added, [{ identifier: { id: 'd', uuid: 'd' }, enabled: true }]); assert.deepEqual(actual.removed, []); assert.deepEqual(actual.updated, []); assert.deepEqual(actual.remote, expected); -- GitLab