forked from organicmaps/organicmaps
[ios] fix icloud initial sync bug when some files are not downloaded at start
https://github.com/organicmaps/organicmaps/issues/10221 Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
This commit is contained in:
parent
9c8b6d934c
commit
6b6b7d145e
3 changed files with 63 additions and 7 deletions
|
@ -22,7 +22,7 @@ enum IncomingSynchronizationEvent {
|
|||
case didUpdateCloudContents(contents: CloudContents, update: CloudContentsUpdate)
|
||||
}
|
||||
|
||||
enum OutgoingSynchronizationEvent {
|
||||
enum OutgoingSynchronizationEvent: Equatable {
|
||||
case startDownloading(CloudMetadataItem)
|
||||
|
||||
case createLocalItem(with: CloudMetadataItem)
|
||||
|
@ -110,16 +110,21 @@ final class iCloudSynchronizationStateResolver: SynchronizationStateResolver {
|
|||
- all items that are in the local container but not in the cloud container will be created in the cloud container
|
||||
*/
|
||||
localContents.forEach { localItem in
|
||||
if let cloudItem = cloudContents.firstByName(localItem), localItem.lastModificationDate != cloudItem.lastModificationDate {
|
||||
events.append(.resolveInitialSynchronizationConflict(localItem))
|
||||
events.append(.updateLocalItem(with: cloudItem))
|
||||
if let cloudItem = cloudContents.downloaded.firstByName(localItem), localItem.lastModificationDate != cloudItem.lastModificationDate {
|
||||
if cloudItem.isDownloaded {
|
||||
events.append(.resolveInitialSynchronizationConflict(localItem))
|
||||
events.append(.updateLocalItem(with: cloudItem))
|
||||
} else {
|
||||
events.append(.startDownloading(cloudItem))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let itemsToCreateInCloudContainer = localContents.filter { !cloudContents.containsByName($0) }
|
||||
let itemsToCreateInLocalContainer = cloudContents.filter { !localContents.containsByName($0) }
|
||||
events.append(contentsOf: itemsToCreateInCloudContainer.map { .createCloudItem(with: $0) })
|
||||
events.append(contentsOf: itemsToCreateInLocalContainer.map { .createLocalItem(with: $0) })
|
||||
itemsToCreateInLocalContainer.notDownloaded.forEach { events.append(.startDownloading($0)) }
|
||||
itemsToCreateInLocalContainer.downloaded.forEach { events.append(.createLocalItem(with: $0)) }
|
||||
itemsToCreateInCloudContainer.forEach { events.append(.createCloudItem(with: $0)) }
|
||||
|
||||
events.append(.didFinishInitialSynchronization)
|
||||
isInitialSynchronization = false
|
||||
|
|
|
@ -108,7 +108,7 @@ final class DefaultLocalDirectoryMonitorTests: XCTestCase {
|
|||
let file3URL = tempDirectory.appendingPathComponent("test3.jpg")
|
||||
let correctFileURL = tempDirectory.appendingPathComponent("test.kml")
|
||||
|
||||
var fileData = Data(count: 12)
|
||||
let fileData = Data(count: 12)
|
||||
try! fileData.write(to: file1URL, options: .atomic)
|
||||
try! fileData.write(to: file2URL, options: .atomic)
|
||||
try! fileData.write(to: file3URL, options: .atomic)
|
||||
|
|
|
@ -98,6 +98,57 @@ final class SynchronizationtateManagerTests: XCTestCase {
|
|||
XCTAssertTrue(outgoingEvents.contains { if case .createCloudItem(_) = $0 { return true } else { return false } }, "Expected creation of cloud item for localFile")
|
||||
}
|
||||
|
||||
func testInitialSynchronizationWhenCloudFilesAreNotDownloadedTheDownloadingShouldStart () {
|
||||
syncStateManager = iCloudSynchronizationStateResolver(isInitialSynchronization: true)
|
||||
|
||||
let localItem1 = LocalMetadataItem.stub(fileName: "file1", lastModificationDate: TimeInterval(1))
|
||||
let cloudItem1 = CloudMetadataItem.stub(fileName: "file1", lastModificationDate: TimeInterval(2))
|
||||
let cloudItem2 = CloudMetadataItem.stub(fileName: "file2", lastModificationDate: TimeInterval(3), isDownloaded: false)
|
||||
let cloudItem3 = CloudMetadataItem.stub(fileName: "file3", lastModificationDate: TimeInterval(4))
|
||||
|
||||
let localItems = LocalContents([localItem1])
|
||||
let cloudItems = CloudContents([cloudItem1, cloudItem2, cloudItem3])
|
||||
|
||||
outgoingEvents.append(contentsOf: syncStateManager.resolveEvent(.didFinishGatheringLocalContents(localItems)))
|
||||
outgoingEvents.append(contentsOf: syncStateManager.resolveEvent(.didFinishGatheringCloudContents(cloudItems)))
|
||||
|
||||
XCTAssertEqual(outgoingEvents.count, 5)
|
||||
|
||||
outgoingEvents.forEach { event in
|
||||
switch event {
|
||||
case .resolveInitialSynchronizationConflict(let item):
|
||||
// copy local file with a new name and replace the original with the cloud file
|
||||
XCTAssertEqual(item, localItem1)
|
||||
case .updateLocalItem(let item):
|
||||
XCTAssertEqual(item, cloudItem1)
|
||||
case .startDownloading(let item):
|
||||
XCTAssertEqual(item, cloudItem2)
|
||||
case .createLocalItem(let item):
|
||||
XCTAssertEqual(item, cloudItem3)
|
||||
case .didFinishInitialSynchronization:
|
||||
XCTAssertTrue(event == outgoingEvents.last)
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
|
||||
// update the cloud items with the new downloaded status
|
||||
let cloudItem2Downloaded = CloudMetadataItem.stub(fileName: "file2", lastModificationDate: TimeInterval(3))
|
||||
let newCloudItems = [cloudItem1, cloudItem2Downloaded, cloudItem3]
|
||||
let cloudUpdate = CloudContentsUpdate(added: [], updated: [cloudItem2Downloaded], removed: [])
|
||||
outgoingEvents = syncStateManager.resolveEvent(.didUpdateCloudContents(contents: newCloudItems, update: cloudUpdate))
|
||||
|
||||
XCTAssertEqual(outgoingEvents.count, 1)
|
||||
outgoingEvents.forEach { event in
|
||||
switch event {
|
||||
case .createLocalItem(let item):
|
||||
XCTAssertEqual(item, cloudItem2Downloaded)
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Test didFinishGathering without errors and after initial synchronization
|
||||
func testDidFinishGatheringWhenCloudAndLocalIsEmpty() {
|
||||
let localItems: LocalContents = []
|
||||
|
|
Loading…
Add table
Reference in a new issue