Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
a6786e8b
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a6786e8b
编写于
2月 18, 2020
作者:
S
Sandeep Somavarapu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
#90076
- Adopt to new v1 URLs - Add end to ened sync tests
上级
12a674ac
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
632 addition
and
39 deletion
+632
-39
src/vs/platform/userDataSync/common/userDataSync.ts
src/vs/platform/userDataSync/common/userDataSync.ts
+12
-8
src/vs/platform/userDataSync/common/userDataSyncService.ts
src/vs/platform/userDataSync/common/userDataSyncService.ts
+1
-1
src/vs/platform/userDataSync/common/userDataSyncStoreService.ts
.../platform/userDataSync/common/userDataSyncStoreService.ts
+4
-5
src/vs/platform/userDataSync/test/common/keybindingsMerge.test.ts
...latform/userDataSync/test/common/keybindingsMerge.test.ts
+2
-25
src/vs/platform/userDataSync/test/common/userDataSyncClient.ts
...s/platform/userDataSync/test/common/userDataSyncClient.ts
+239
-0
src/vs/platform/userDataSync/test/common/userDataSyncService.test.ts
...form/userDataSync/test/common/userDataSyncService.test.ts
+374
-0
未找到文件。
src/vs/platform/userDataSync/common/userDataSync.ts
浏览文件 @
a6786e8b
...
...
@@ -18,7 +18,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import
{
IStringDictionary
}
from
'
vs/base/common/collections
'
;
import
{
FormattingOptions
}
from
'
vs/base/common/jsonFormatter
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
isEqual
}
from
'
vs/base/common/resources
'
;
import
{
isEqual
,
joinPath
}
from
'
vs/base/common/resources
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
export
const
CONFIGURATION_SYNC_STORE_KEY
=
'
configurationSync.store
'
;
...
...
@@ -120,23 +120,27 @@ export interface IUserData {
}
export
interface
IUserDataSyncStore
{
url
:
string
;
url
:
URI
;
authenticationProviderId
:
string
;
}
export
function
getUserDataSyncStore
(
configurationService
:
IConfigurationService
):
IUserDataSyncStore
|
undefined
{
const
value
=
configurationService
.
getValue
<
IUserDataSyncStore
>
(
CONFIGURATION_SYNC_STORE_KEY
);
return
value
&&
value
.
url
&&
value
.
authenticationProviderId
?
value
:
undefined
;
const
value
=
configurationService
.
getValue
<
{
url
:
string
,
authenticationProviderId
:
string
}
>
(
CONFIGURATION_SYNC_STORE_KEY
);
if
(
value
&&
value
.
url
&&
value
.
authenticationProviderId
)
{
return
{
url
:
joinPath
(
URI
.
parse
(
value
.
url
),
'
v1
'
),
authenticationProviderId
:
value
.
authenticationProviderId
};
}
return
undefined
;
}
export
const
ALL_RESOURCE_KEYS
:
ResourceKey
[]
=
[
'
settings
'
,
'
keybindings
'
,
'
extensions
'
,
'
globalState
'
];
export
type
ResourceKey
=
'
settings
'
|
'
keybindings
'
|
'
extensions
'
|
'
globalState
'
;
export
interface
IUserDataManifest
{
settings
:
string
;
keybindings
:
string
;
extensions
:
string
;
globalState
:
string
;
latest
?:
Record
<
ResourceKey
,
string
>
session
:
string
;
}
export
const
IUserDataSyncStoreService
=
createDecorator
<
IUserDataSyncStoreService
>
(
'
IUserDataSyncStoreService
'
);
...
...
src/vs/platform/userDataSync/common/userDataSyncService.ts
浏览文件 @
a6786e8b
...
...
@@ -106,7 +106,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
for
(
const
synchroniser
of
this
.
synchronisers
)
{
try
{
await
synchroniser
.
sync
(
manifest
?
manif
est
[
synchroniser
.
resourceKey
]
:
undefined
);
await
synchroniser
.
sync
(
manifest
&&
manifest
.
latest
?
manifest
.
lat
est
[
synchroniser
.
resourceKey
]
:
undefined
);
}
catch
(
e
)
{
this
.
handleSyncError
(
e
,
synchroniser
.
source
);
}
...
...
src/vs/platform/userDataSync/common/userDataSyncStoreService.ts
浏览文件 @
a6786e8b
...
...
@@ -6,7 +6,6 @@
import
{
Disposable
,
}
from
'
vs/base/common/lifecycle
'
;
import
{
IUserData
,
IUserDataSyncStoreService
,
UserDataSyncErrorCode
,
IUserDataSyncStore
,
getUserDataSyncStore
,
IUserDataAuthTokenService
,
SyncSource
,
UserDataSyncStoreError
,
IUserDataSyncLogService
,
IUserDataManifest
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
IRequestService
,
asText
,
isSuccess
,
asJson
}
from
'
vs/platform/request/common/request
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
joinPath
}
from
'
vs/base/common/resources
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
IHeaders
,
IRequestOptions
,
IRequestContext
}
from
'
vs/base/parts/request/common/request
'
;
...
...
@@ -33,7 +32,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
throw
new
Error
(
'
No settings sync store url configured.
'
);
}
const
url
=
joinPath
(
URI
.
parse
(
this
.
userDataSyncStore
.
url
)
,
'
resource
'
,
key
,
'
latest
'
).
toString
();
const
url
=
joinPath
(
this
.
userDataSyncStore
.
url
,
'
resource
'
,
key
,
'
latest
'
).
toString
();
const
headers
:
IHeaders
=
{};
// Disable caching as they are cached by synchronisers
headers
[
'
Cache-Control
'
]
=
'
no-cache
'
;
...
...
@@ -65,7 +64,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
throw
new
Error
(
'
No settings sync store url configured.
'
);
}
const
url
=
joinPath
(
URI
.
parse
(
this
.
userDataSyncStore
.
url
)
,
'
resource
'
,
key
).
toString
();
const
url
=
joinPath
(
this
.
userDataSyncStore
.
url
,
'
resource
'
,
key
).
toString
();
const
headers
:
IHeaders
=
{
'
Content-Type
'
:
'
text/plain
'
};
if
(
ref
)
{
headers
[
'
If-Match
'
]
=
ref
;
...
...
@@ -89,7 +88,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
throw
new
Error
(
'
No settings sync store url configured.
'
);
}
const
url
=
joinPath
(
URI
.
parse
(
this
.
userDataSyncStore
.
url
),
'
resource
'
,
'
lat
est
'
).
toString
();
const
url
=
joinPath
(
this
.
userDataSyncStore
.
url
,
'
manif
est
'
).
toString
();
const
headers
:
IHeaders
=
{
'
Content-Type
'
:
'
application/json
'
};
const
context
=
await
this
.
request
({
type
:
'
GET
'
,
url
,
headers
},
undefined
,
CancellationToken
.
None
);
...
...
@@ -105,7 +104,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
throw
new
Error
(
'
No settings sync store url configured.
'
);
}
const
url
=
joinPath
(
URI
.
parse
(
this
.
userDataSyncStore
.
url
)
,
'
resource
'
).
toString
();
const
url
=
joinPath
(
this
.
userDataSyncStore
.
url
,
'
resource
'
).
toString
();
const
headers
:
IHeaders
=
{
'
Content-Type
'
:
'
text/plain
'
};
const
context
=
await
this
.
request
({
type
:
'
DELETE
'
,
url
,
headers
},
undefined
,
CancellationToken
.
None
);
...
...
src/vs/platform/userDataSync/test/common/keybindingsMerge.test.ts
浏览文件 @
a6786e8b
...
...
@@ -5,11 +5,7 @@
import
*
as
assert
from
'
assert
'
;
import
{
merge
}
from
'
vs/platform/userDataSync/common/keybindingsMerge
'
;
import
{
IStringDictionary
}
from
'
vs/base/common/collections
'
;
import
{
IUserDataSyncUtilService
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
FormattingOptions
}
from
'
vs/base/common/jsonFormatter
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
type
{
IExtensionIdentifier
}
from
'
vs/platform/extensionManagement/common/extensionManagement
'
;
import
{
TestUserDataSyncUtilService
}
from
'
vs/platform/userDataSync/test/common/userDataSyncClient
'
;
suite
(
'
KeybindingsMerge - No Conflicts
'
,
()
=>
{
...
...
@@ -613,7 +609,7 @@ suite('KeybindingsMerge - No Conflicts', () => {
});
async
function
mergeKeybindings
(
localContent
:
string
,
remoteContent
:
string
,
baseContent
:
string
|
null
)
{
const
userDataSyncUtilService
=
new
Mock
UserDataSyncUtilService
();
const
userDataSyncUtilService
=
new
Test
UserDataSyncUtilService
();
const
formattingOptions
=
await
userDataSyncUtilService
.
resolveFormattingOptions
();
return
merge
(
localContent
,
remoteContent
,
baseContent
,
formattingOptions
,
userDataSyncUtilService
);
}
...
...
@@ -621,22 +617,3 @@ async function mergeKeybindings(localContent: string, remoteContent: string, bas
function
stringify
(
value
:
any
):
string
{
return
JSON
.
stringify
(
value
,
null
,
'
\t
'
);
}
class
MockUserDataSyncUtilService
implements
IUserDataSyncUtilService
{
_serviceBrand
:
any
;
async
resolveUserBindings
(
userbindings
:
string
[]):
Promise
<
IStringDictionary
<
string
>>
{
const
keys
:
IStringDictionary
<
string
>
=
{};
for
(
const
keybinding
of
userbindings
)
{
keys
[
keybinding
]
=
keybinding
;
}
return
keys
;
}
async
resolveFormattingOptions
(
file
?:
URI
):
Promise
<
FormattingOptions
>
{
return
{
eol
:
'
\n
'
,
insertSpaces
:
false
,
tabSize
:
4
};
}
async
ignoreExtensionsToSync
(
extensions
:
IExtensionIdentifier
[]):
Promise
<
void
>
{
}
}
src/vs/platform/userDataSync/test/common/userDataSyncClient.ts
0 → 100644
浏览文件 @
a6786e8b
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
IRequestService
}
from
'
vs/platform/request/common/request
'
;
import
{
IRequestOptions
,
IRequestContext
,
IHeaders
}
from
'
vs/base/parts/request/common/request
'
;
import
{
CancellationToken
}
from
'
vs/base/common/cancellation
'
;
import
{
IUserData
,
ResourceKey
,
IUserDataManifest
,
ALL_RESOURCE_KEYS
,
IUserDataAuthTokenService
,
IUserDataSyncLogService
,
IUserDataSyncStoreService
,
IUserDataSyncUtilService
,
IUserDataSyncEnablementService
,
ISettingsSyncService
,
IUserDataSyncService
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
relative
}
from
'
vs/base/common/path
'
;
import
{
bufferToStream
,
VSBuffer
}
from
'
vs/base/common/buffer
'
;
import
{
generateUuid
}
from
'
vs/base/common/uuid
'
;
import
{
UserDataSyncService
}
from
'
vs/platform/userDataSync/common/userDataSyncService
'
;
import
{
TestInstantiationService
}
from
'
vs/platform/instantiation/test/common/instantiationServiceMock
'
;
import
{
IConfigurationService
}
from
'
vs/platform/configuration/common/configuration
'
;
import
{
NullLogService
,
ILogService
}
from
'
vs/platform/log/common/log
'
;
import
{
UserDataSyncStoreService
}
from
'
vs/platform/userDataSync/common/userDataSyncStoreService
'
;
import
{
NullTelemetryService
}
from
'
vs/platform/telemetry/common/telemetryUtils
'
;
import
{
ITelemetryService
}
from
'
vs/platform/telemetry/common/telemetry
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
FileService
}
from
'
vs/platform/files/common/fileService
'
;
import
{
Schemas
}
from
'
vs/base/common/network
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
IStorageService
,
InMemoryStorageService
}
from
'
vs/platform/storage/common/storage
'
;
import
{
URI
}
from
'
vs/base/common/uri
'
;
import
{
joinPath
}
from
'
vs/base/common/resources
'
;
import
{
IStringDictionary
}
from
'
vs/base/common/collections
'
;
import
{
FormattingOptions
}
from
'
vs/base/common/jsonFormatter
'
;
import
{
UserDataSyncEnablementService
}
from
'
vs/platform/userDataSync/common/userDataSyncEnablementService
'
;
import
{
IGlobalExtensionEnablementService
,
IExtensionManagementService
,
IExtensionGalleryService
,
DidInstallExtensionEvent
,
DidUninstallExtensionEvent
}
from
'
vs/platform/extensionManagement/common/extensionManagement
'
;
import
{
GlobalExtensionEnablementService
}
from
'
vs/platform/extensionManagement/common/extensionEnablementService
'
;
import
{
InMemoryFileSystemProvider
}
from
'
vs/platform/files/common/inMemoryFilesystemProvider
'
;
import
{
ConfigurationService
}
from
'
vs/platform/configuration/common/configurationService
'
;
import
{
Disposable
}
from
'
vs/base/common/lifecycle
'
;
import
{
SettingsSynchroniser
}
from
'
vs/platform/userDataSync/common/settingsSync
'
;
import
{
Emitter
}
from
'
vs/base/common/event
'
;
export
class
UserDataSyncClient
extends
Disposable
{
readonly
instantiationService
:
TestInstantiationService
;
constructor
(
readonly
testServer
:
UserDataSyncTestServer
=
new
UserDataSyncTestServer
())
{
super
();
this
.
instantiationService
=
new
TestInstantiationService
();
}
async
setUp
():
Promise
<
void
>
{
const
userDataDirectory
=
URI
.
file
(
'
userdata
'
).
with
({
scheme
:
Schemas
.
inMemory
});
const
userDataSyncHome
=
joinPath
(
userDataDirectory
,
'
.sync
'
);
const
environmentService
=
this
.
instantiationService
.
stub
(
IEnvironmentService
,
<
Partial
<
IEnvironmentService
>>
{
userDataSyncHome
,
settingsResource
:
joinPath
(
userDataDirectory
,
'
settings.json
'
),
settingsSyncPreviewResource
:
joinPath
(
userDataSyncHome
,
'
settings.json
'
),
keybindingsResource
:
joinPath
(
userDataDirectory
,
'
keybindings.json
'
),
keybindingsSyncPreviewResource
:
joinPath
(
userDataSyncHome
,
'
keybindings.json
'
),
argvResource
:
joinPath
(
userDataDirectory
,
'
argv.json
'
),
});
const
logService
=
new
NullLogService
();
this
.
instantiationService
.
stub
(
ILogService
,
logService
);
const
fileService
=
this
.
_register
(
new
FileService
(
logService
));
fileService
.
registerProvider
(
Schemas
.
inMemory
,
new
InMemoryFileSystemProvider
());
this
.
instantiationService
.
stub
(
IFileService
,
fileService
);
this
.
instantiationService
.
stub
(
IStorageService
,
new
InMemoryStorageService
());
await
fileService
.
writeFile
(
environmentService
.
settingsResource
,
VSBuffer
.
fromString
(
JSON
.
stringify
({
'
configurationSync.store
'
:
{
url
:
this
.
testServer
.
url
,
authenticationProviderId
:
'
test
'
}
})));
await
fileService
.
writeFile
(
environmentService
.
keybindingsResource
,
VSBuffer
.
fromString
(
JSON
.
stringify
([])));
const
configurationService
=
new
ConfigurationService
(
environmentService
.
settingsResource
,
fileService
);
await
configurationService
.
initialize
();
this
.
instantiationService
.
stub
(
IConfigurationService
,
configurationService
);
this
.
instantiationService
.
stub
(
IRequestService
,
this
.
testServer
);
this
.
instantiationService
.
stub
(
IUserDataAuthTokenService
,
<
Partial
<
IUserDataAuthTokenService
>>
{
onDidChangeToken
:
new
Emitter
<
string
|
undefined
>
().
event
,
async
getToken
()
{
return
'
token
'
;
}
});
this
.
instantiationService
.
stub
(
IUserDataSyncLogService
,
logService
);
this
.
instantiationService
.
stub
(
ITelemetryService
,
NullTelemetryService
);
this
.
instantiationService
.
stub
(
IUserDataSyncStoreService
,
this
.
instantiationService
.
createInstance
(
UserDataSyncStoreService
));
this
.
instantiationService
.
stub
(
IUserDataSyncUtilService
,
new
TestUserDataSyncUtilService
());
this
.
instantiationService
.
stub
(
IUserDataSyncEnablementService
,
this
.
instantiationService
.
createInstance
(
UserDataSyncEnablementService
));
this
.
instantiationService
.
stub
(
IGlobalExtensionEnablementService
,
this
.
instantiationService
.
createInstance
(
GlobalExtensionEnablementService
));
this
.
instantiationService
.
stub
(
IExtensionManagementService
,
<
Partial
<
IExtensionManagementService
>>
{
async
getInstalled
()
{
return
[];
},
onDidInstallExtension
:
new
Emitter
<
DidInstallExtensionEvent
>
().
event
,
onDidUninstallExtension
:
new
Emitter
<
DidUninstallExtensionEvent
>
().
event
,
});
this
.
instantiationService
.
stub
(
IExtensionGalleryService
,
<
Partial
<
IExtensionGalleryService
>>
{
isEnabled
()
{
return
true
;
},
async
getCompatibleExtension
()
{
return
null
;
}
});
this
.
instantiationService
.
stub
(
ISettingsSyncService
,
this
.
instantiationService
.
createInstance
(
SettingsSynchroniser
));
this
.
instantiationService
.
stub
(
IUserDataSyncService
,
this
.
instantiationService
.
createInstance
(
UserDataSyncService
));
}
}
export
class
UserDataSyncTestServer
implements
IRequestService
{
_serviceBrand
:
any
;
readonly
url
:
string
=
'
http://host:3000
'
;
private
session
:
string
|
null
=
null
;
private
readonly
data
:
Map
<
ResourceKey
,
IUserData
>
=
new
Map
<
ResourceKey
,
IUserData
>
();
private
_requests
:
{
url
:
string
,
type
:
string
,
headers
?:
IHeaders
}[]
=
[];
get
requests
():
{
url
:
string
,
type
:
string
,
headers
?:
IHeaders
}[]
{
return
this
.
_requests
;
}
private
_responses
:
{
status
:
number
}[]
=
[];
get
responses
():
{
status
:
number
}[]
{
return
this
.
_responses
;
}
reset
():
void
{
this
.
_requests
=
[];
this
.
_responses
=
[];
}
async
resolveProxy
(
url
:
string
):
Promise
<
string
|
undefined
>
{
return
url
;
}
async
request
(
options
:
IRequestOptions
,
token
:
CancellationToken
):
Promise
<
IRequestContext
>
{
const
headers
:
IHeaders
=
{};
if
(
options
.
headers
)
{
if
(
options
.
headers
[
'
If-None-Match
'
])
{
headers
[
'
If-None-Match
'
]
=
options
.
headers
[
'
If-None-Match
'
];
}
if
(
options
.
headers
[
'
If-Match
'
])
{
headers
[
'
If-Match
'
]
=
options
.
headers
[
'
If-Match
'
];
}
}
this
.
_requests
.
push
({
url
:
options
.
url
!
,
type
:
options
.
type
!
,
headers
});
const
requestContext
=
await
this
.
doRequest
(
options
);
this
.
_responses
.
push
({
status
:
requestContext
.
res
.
statusCode
!
});
return
requestContext
;
}
private
async
doRequest
(
options
:
IRequestOptions
):
Promise
<
IRequestContext
>
{
const
relativePath
=
relative
(
`
${
this
.
url
}
/v1/`
,
options
.
url
!
);
const
segments
=
relativePath
?
relativePath
.
split
(
'
/
'
)
:
[];
if
(
options
.
type
===
'
GET
'
&&
segments
.
length
===
1
&&
segments
[
0
]
===
'
manifest
'
)
{
return
this
.
getManifest
(
options
.
headers
);
}
if
(
options
.
type
===
'
GET
'
&&
segments
.
length
===
3
&&
segments
[
0
]
===
'
resource
'
&&
segments
[
2
]
===
'
latest
'
)
{
return
this
.
getLatestData
(
segments
[
1
],
options
.
headers
);
}
if
(
options
.
type
===
'
POST
'
&&
segments
.
length
===
2
&&
segments
[
0
]
===
'
resource
'
)
{
return
this
.
writeData
(
segments
[
1
],
options
.
data
,
options
.
headers
);
}
if
(
options
.
type
===
'
DELETE
'
&&
segments
.
length
===
1
&&
segments
[
0
]
===
'
resource
'
)
{
return
this
.
clear
(
options
.
headers
);
}
return
this
.
toResponse
(
501
);
}
private
async
getManifest
(
headers
?:
IHeaders
):
Promise
<
IRequestContext
>
{
if
(
this
.
session
)
{
const
latest
:
Record
<
ResourceKey
,
string
>
=
Object
.
create
({});
const
manifest
:
IUserDataManifest
=
{
session
:
this
.
session
,
latest
};
this
.
data
.
forEach
((
value
,
key
)
=>
latest
[
key
]
=
value
.
ref
);
return
this
.
toResponse
(
200
,
{
'
Content-Type
'
:
'
application/json
'
},
JSON
.
stringify
(
manifest
));
}
return
this
.
toResponse
(
204
);
}
private
async
getLatestData
(
resource
:
string
,
headers
:
IHeaders
=
{}):
Promise
<
IRequestContext
>
{
const
resourceKey
=
ALL_RESOURCE_KEYS
.
find
(
key
=>
key
===
resource
);
if
(
resourceKey
)
{
const
data
=
this
.
data
.
get
(
resourceKey
);
if
(
!
data
)
{
return
this
.
toResponse
(
204
,
{
etag
:
'
0
'
});
}
if
(
headers
[
'
If-None-Match
'
]
===
data
.
ref
)
{
return
this
.
toResponse
(
304
);
}
return
this
.
toResponse
(
200
,
{
etag
:
data
.
ref
},
data
.
content
||
''
);
}
return
this
.
toResponse
(
204
);
}
private
async
writeData
(
resource
:
string
,
content
:
string
=
''
,
headers
:
IHeaders
=
{}):
Promise
<
IRequestContext
>
{
if
(
!
headers
[
'
If-Match
'
])
{
return
this
.
toResponse
(
428
);
}
if
(
!
this
.
session
)
{
this
.
session
=
generateUuid
();
}
const
resourceKey
=
ALL_RESOURCE_KEYS
.
find
(
key
=>
key
===
resource
);
if
(
resourceKey
)
{
const
data
=
this
.
data
.
get
(
resourceKey
);
if
(
headers
[
'
If-Match
'
]
!==
(
data
?
data
.
ref
:
'
0
'
))
{
return
this
.
toResponse
(
412
);
}
const
ref
=
`
${
parseInt
(
data
?.
ref
||
'
0
'
)
+
1
}
`
;
this
.
data
.
set
(
resourceKey
,
{
ref
,
content
});
return
this
.
toResponse
(
200
,
{
etag
:
ref
});
}
return
this
.
toResponse
(
204
);
}
private
async
clear
(
headers
?:
IHeaders
):
Promise
<
IRequestContext
>
{
this
.
data
.
clear
();
this
.
session
=
null
;
return
this
.
toResponse
(
204
);
}
private
toResponse
(
statusCode
:
number
,
headers
?:
IHeaders
,
data
?:
string
):
IRequestContext
{
return
{
res
:
{
headers
:
headers
||
{},
statusCode
},
stream
:
bufferToStream
(
VSBuffer
.
fromString
(
data
||
''
))
};
}
}
export
class
TestUserDataSyncUtilService
implements
IUserDataSyncUtilService
{
_serviceBrand
:
any
;
async
resolveUserBindings
(
userbindings
:
string
[]):
Promise
<
IStringDictionary
<
string
>>
{
const
keys
:
IStringDictionary
<
string
>
=
{};
for
(
const
keybinding
of
userbindings
)
{
keys
[
keybinding
]
=
keybinding
;
}
return
keys
;
}
async
resolveFormattingOptions
(
file
?:
URI
):
Promise
<
FormattingOptions
>
{
return
{
eol
:
'
\n
'
,
insertSpaces
:
false
,
tabSize
:
4
};
}
}
src/vs/platform/userDataSync/test/common/userDataSyncService.test.ts
0 → 100644
浏览文件 @
a6786e8b
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
*
as
assert
from
'
assert
'
;
import
{
IUserDataSyncService
,
UserDataSyncError
,
UserDataSyncErrorCode
}
from
'
vs/platform/userDataSync/common/userDataSync
'
;
import
{
UserDataSyncClient
,
UserDataSyncTestServer
}
from
'
vs/platform/userDataSync/test/common/userDataSyncClient
'
;
import
{
DisposableStore
}
from
'
vs/base/common/lifecycle
'
;
import
{
IFileService
}
from
'
vs/platform/files/common/files
'
;
import
{
IEnvironmentService
}
from
'
vs/platform/environment/common/environment
'
;
import
{
VSBuffer
}
from
'
vs/base/common/buffer
'
;
suite
(
'
UserDataSyncService
'
,
()
=>
{
const
disposableStore
=
new
DisposableStore
();
teardown
(()
=>
disposableStore
.
clear
());
test
(
'
test first time sync ever
'
,
async
()
=>
{
// Setup the client
const
target
=
new
UserDataSyncTestServer
();
const
client
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
client
.
setUp
();
const
testObject
=
client
.
instantiationService
.
get
(
IUserDataSyncService
);
// Sync for first time
await
testObject
.
sync
();
assert
.
deepEqual
(
target
.
requests
,
[
// Manifest
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
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
'
}
},
// 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
:
{}
},
{
type
:
'
POST
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions`
,
headers
:
{
'
If-Match
'
:
'
0
'
}
}
]);
});
test
(
'
test first time sync from the client with no changes - pull
'
,
async
()
=>
{
const
target
=
new
UserDataSyncTestServer
();
// Setup and sync from the first client
const
client
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
client
.
setUp
();
await
client
.
instantiationService
.
get
(
IUserDataSyncService
).
sync
();
// Setup the test client
const
testClient
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
testClient
.
setUp
();
const
testObject
=
testClient
.
instantiationService
.
get
(
IUserDataSyncService
);
// Sync (pull) from the test client
target
.
reset
();
await
testObject
.
isFirstTimeSyncWithMerge
();
await
testObject
.
pull
();
assert
.
deepEqual
(
target
.
requests
,
[
// Manifest
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
// Settings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
// Keybindings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{}
},
// Global state
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{}
},
// Extensions
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions/latest`
,
headers
:
{}
},
]);
});
test
(
'
test first time sync from the client with changes - pull
'
,
async
()
=>
{
const
target
=
new
UserDataSyncTestServer
();
// Setup and sync from the first client
const
client
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
client
.
setUp
();
await
client
.
instantiationService
.
get
(
IUserDataSyncService
).
sync
();
// Setup the test client with changes
const
testClient
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
testClient
.
setUp
();
const
testObject
=
testClient
.
instantiationService
.
get
(
IUserDataSyncService
);
const
fileService
=
testClient
.
instantiationService
.
get
(
IFileService
);
const
environmentService
=
testClient
.
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
(
environmentService
.
argvResource
,
VSBuffer
.
fromString
(
JSON
.
stringify
({
'
locale
'
:
'
de
'
})));
// Sync (pull) from the test client
target
.
reset
();
await
testObject
.
isFirstTimeSyncWithMerge
();
await
testObject
.
pull
();
assert
.
deepEqual
(
target
.
requests
,
[
// Manifest
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
// Settings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
// Keybindings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{}
},
// Global state
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{}
},
// Extensions
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions/latest`
,
headers
:
{}
},
]);
});
test
(
'
test first time sync from the client with no changes - merge
'
,
async
()
=>
{
const
target
=
new
UserDataSyncTestServer
();
// Setup and sync from the first client
const
client
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
client
.
setUp
();
await
client
.
instantiationService
.
get
(
IUserDataSyncService
).
sync
();
// Setup the test client
const
testClient
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
testClient
.
setUp
();
const
testObject
=
testClient
.
instantiationService
.
get
(
IUserDataSyncService
);
// Sync (merge) from the test client
target
.
reset
();
await
testObject
.
isFirstTimeSyncWithMerge
();
await
testObject
.
sync
();
assert
.
deepEqual
(
target
.
requests
,
[
// Manifest
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
// Settings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
// Keybindings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{}
},
// Global state
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{}
},
// Extensions
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions/latest`
,
headers
:
{}
},
]);
});
test
(
'
test first time sync from the client with changes - merge
'
,
async
()
=>
{
const
target
=
new
UserDataSyncTestServer
();
// Setup and sync from the first client
const
client
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
client
.
setUp
();
await
client
.
instantiationService
.
get
(
IUserDataSyncService
).
sync
();
// Setup the test client with changes
const
testClient
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
testClient
.
setUp
();
const
fileService
=
testClient
.
instantiationService
.
get
(
IFileService
);
const
environmentService
=
testClient
.
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
(
environmentService
.
argvResource
,
VSBuffer
.
fromString
(
JSON
.
stringify
({
'
locale
'
:
'
de
'
})));
const
testObject
=
testClient
.
instantiationService
.
get
(
IUserDataSyncService
);
// Sync (merge) from the test client
target
.
reset
();
await
testObject
.
isFirstTimeSyncWithMerge
();
await
testObject
.
sync
();
assert
.
deepEqual
(
target
.
requests
,
[
// Manifest
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
// Settings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{}
},
{
type
:
'
POST
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings`
,
headers
:
{
'
If-Match
'
:
'
1
'
}
},
// Keybindings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{}
},
{
type
:
'
POST
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings`
,
headers
:
{
'
If-Match
'
:
'
1
'
}
},
// Global state
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{}
},
{
type
:
'
POST
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState`
,
headers
:
{
'
If-Match
'
:
'
1
'
}
},
// Extensions
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions/latest`
,
headers
:
{}
},
]);
});
test
(
'
test sync when there are no changes
'
,
async
()
=>
{
const
target
=
new
UserDataSyncTestServer
();
// Setup and sync from the client
const
client
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
client
.
setUp
();
const
testObject
=
client
.
instantiationService
.
get
(
IUserDataSyncService
);
await
testObject
.
sync
();
// sync from the client again
target
.
reset
();
await
testObject
.
sync
();
assert
.
deepEqual
(
target
.
requests
,
[
// Manifest
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
]);
});
test
(
'
test sync when there are local changes
'
,
async
()
=>
{
const
target
=
new
UserDataSyncTestServer
();
// Setup and sync from the client
const
client
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
client
.
setUp
();
const
testObject
=
client
.
instantiationService
.
get
(
IUserDataSyncService
);
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
(
environmentService
.
argvResource
,
VSBuffer
.
fromString
(
JSON
.
stringify
({
'
locale
'
:
'
de
'
})));
// Sync from the client
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
'
}
},
// Global state
{
type
:
'
POST
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState`
,
headers
:
{
'
If-Match
'
:
'
1
'
}
},
]);
});
test
(
'
test sync when there are remote changes
'
,
async
()
=>
{
const
target
=
new
UserDataSyncTestServer
();
// Sync from first client
const
client
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
client
.
setUp
();
await
client
.
instantiationService
.
get
(
IUserDataSyncService
).
sync
();
// Sync from test client
const
testClient
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
testClient
.
setUp
();
const
testObject
=
testClient
.
instantiationService
.
get
(
IUserDataSyncService
);
await
testObject
.
sync
();
// Do changes in first client and sync
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
(
environmentService
.
argvResource
,
VSBuffer
.
fromString
(
JSON
.
stringify
({
'
locale
'
:
'
de
'
})));
await
client
.
instantiationService
.
get
(
IUserDataSyncService
).
sync
();
// Sync from test client
target
.
reset
();
await
testObject
.
sync
();
assert
.
deepEqual
(
target
.
requests
,
[
// Manifest
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
// Settings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/settings/latest`
,
headers
:
{
'
If-None-Match
'
:
'
1
'
}
},
// Keybindings
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/keybindings/latest`
,
headers
:
{
'
If-None-Match
'
:
'
1
'
}
},
// Global state
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/resource/globalState/latest`
,
headers
:
{
'
If-None-Match
'
:
'
1
'
}
},
]);
});
test
(
'
test delete
'
,
async
()
=>
{
const
target
=
new
UserDataSyncTestServer
();
// Sync from the client
const
testClient
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
testClient
.
setUp
();
const
testObject
=
testClient
.
instantiationService
.
get
(
IUserDataSyncService
);
await
testObject
.
sync
();
// Reset from the client
target
.
reset
();
await
testObject
.
reset
();
assert
.
deepEqual
(
target
.
requests
,
[
// Manifest
{
type
:
'
DELETE
'
,
url
:
`
${
target
.
url
}
/v1/resource`
,
headers
:
{}
},
]);
});
test
(
'
test delete and sync
'
,
async
()
=>
{
const
target
=
new
UserDataSyncTestServer
();
// Sync from the client
const
testClient
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
testClient
.
setUp
();
const
testObject
=
testClient
.
instantiationService
.
get
(
IUserDataSyncService
);
await
testObject
.
sync
();
// Reset from the client
await
testObject
.
reset
();
// Sync again
target
.
reset
();
await
testObject
.
sync
();
assert
.
deepEqual
(
target
.
requests
,
[
// Manifest
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
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
'
}
},
// 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
:
{}
},
{
type
:
'
POST
'
,
url
:
`
${
target
.
url
}
/v1/resource/extensions`
,
headers
:
{
'
If-Match
'
:
'
0
'
}
}
]);
});
test
(
'
test delete on one client throws 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
client
.
instantiationService
.
get
(
IUserDataSyncService
).
sync
();
// Set up and sync from the test client
const
testClient
=
disposableStore
.
add
(
new
UserDataSyncClient
(
target
));
await
testClient
.
setUp
();
const
testObject
=
testClient
.
instantiationService
.
get
(
IUserDataSyncService
);
await
testObject
.
sync
();
// Reset from the first client
await
client
.
instantiationService
.
get
(
IUserDataSyncService
).
reset
();
// Sync from the test client
target
.
reset
();
try
{
await
testObject
.
sync
();
}
catch
(
e
)
{
assert
.
ok
(
e
instanceof
UserDataSyncError
);
assert
.
deepEqual
((
<
UserDataSyncError
>
e
).
code
,
UserDataSyncErrorCode
.
TurnedOff
);
assert
.
deepEqual
(
target
.
requests
,
[
// Manifest
{
type
:
'
GET
'
,
url
:
`
${
target
.
url
}
/v1/manifest`
,
headers
:
{}
},
]);
return
;
}
throw
assert
.
fail
(
'
Should fail with turned off error
'
);
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录