From c2c18618ba0f33b0f67a7d0a8ebe15b338a4f6df Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Thu, 29 Sep 2022 18:57:07 +0200 Subject: [PATCH] Create BackupStorage.onDisk implementation --- .../Utils/BackupStorage.swift | 24 +++- .../Utils/BackupStorageTests.swift | 103 +++++++++++++----- 2 files changed, 91 insertions(+), 36 deletions(-) diff --git a/Sources/XXMessengerClient/Utils/BackupStorage.swift b/Sources/XXMessengerClient/Utils/BackupStorage.swift index b13c86cb..e85e2e86 100644 --- a/Sources/XXMessengerClient/Utils/BackupStorage.swift +++ b/Sources/XXMessengerClient/Utils/BackupStorage.swift @@ -18,28 +18,39 @@ public struct BackupStorage { public typealias Observer = (Backup?) -> Void - public var store: (Data) -> Void + public var store: (Data) throws -> Void public var observe: (@escaping Observer) -> Cancellable - public var remove: () -> Void + public var remove: () throws -> Void } extension BackupStorage { - public static func live( - now: @escaping () -> Date + public static func onDisk( + now: @escaping () -> Date = Date.init, + fileManager: MessengerFileManager = .live(), + path: String = FileManager.default + .urls(for: .applicationSupportDirectory, in: .userDomainMask) + .first! + .appendingPathComponent("backup.xxm") + .path ) -> BackupStorage { var observers: [UUID: Observer] = [:] var backup: Backup? func notifyObservers() { observers.values.forEach { $0(backup) } } - + if let fileData = try? fileManager.loadFile(path), + let fileDate = try? fileManager.modifiedTime(path) { + backup = Backup(date: fileDate, data: fileData) + } return BackupStorage( store: { data in - backup = Backup( + let newBackup = Backup( date: now(), data: data ) + backup = newBackup notifyObservers() + try fileManager.saveFile(path, newBackup.data) }, observe: { observer in let id = UUID() @@ -52,6 +63,7 @@ extension BackupStorage { remove: { backup = nil notifyObservers() + try fileManager.removeItem(path) } ) } diff --git a/Tests/XXMessengerClientTests/Utils/BackupStorageTests.swift b/Tests/XXMessengerClientTests/Utils/BackupStorageTests.swift index 3dc8272e..d373ce6e 100644 --- a/Tests/XXMessengerClientTests/Utils/BackupStorageTests.swift +++ b/Tests/XXMessengerClientTests/Utils/BackupStorageTests.swift @@ -3,63 +3,98 @@ import XCTest @testable import XXMessengerClient final class BackupStorageTests: XCTestCase { - func testStorage() { + func testStorage() throws { + var actions: [Action]! + var now: Date = .init(0) - let storage: BackupStorage = .live( - now: { now } + let path = "backup-path" + let fileData = "file-data".data(using: .utf8)! + let fileDate = Date(123) + var fileManager = MessengerFileManager.unimplemented + fileManager.loadFile = { path in + actions.append(.didLoadFile(path)) + return fileData + } + fileManager.modifiedTime = { path in + actions.append(.didGetModifiedTime(path)) + return fileDate + } + fileManager.saveFile = { path, data in + actions.append(.didSaveFile(path, data)) + } + fileManager.removeItem = { path in + actions.append(.didRemoveItem(path)) + } + actions = [] + let storage: BackupStorage = .onDisk( + now: { now }, + fileManager: fileManager, + path: path ) - var didObserveA: [BackupStorage.Backup?] = [] + XCTAssertNoDifference(actions, [ + .didLoadFile(path), + .didGetModifiedTime(path), + ]) + + actions = [] let observerA = storage.observe { backup in - didObserveA.append(backup) + actions.append(.didObserve("A", backup)) } - XCTAssertNoDifference(didObserveA, [nil]) + XCTAssertNoDifference(actions, [ + .didObserve("A", .init(date: fileDate, data: fileData)) + ]) + actions = [] now = .init(1) - didObserveA = [] let data1 = "data-1".data(using: .utf8)! - storage.store(data1) + try storage.store(data1) - XCTAssertNoDifference(didObserveA, [.init(date: .init(1), data: data1)]) + XCTAssertNoDifference(actions, [ + .didObserve("A", .init(date: .init(1), data: data1)), + .didSaveFile(path, data1), + ]) + actions = [] now = .init(2) - didObserveA = [] - var didObserveB: [BackupStorage.Backup?] = [] let observerB = storage.observe { backup in - didObserveB.append(backup) + actions.append(.didObserve("B", backup)) } - XCTAssertNoDifference(didObserveA, []) - XCTAssertNoDifference(didObserveB, [.init(date: .init(1), data: data1)]) + XCTAssertNoDifference(actions, [ + .didObserve("B", .init(date: .init(1), data: data1)) + ]) + actions = [] now = .init(3) - didObserveA = [] - didObserveB = [] + observerA.cancel() let data2 = "data-2".data(using: .utf8)! - storage.store(data2) + try storage.store(data2) - XCTAssertNoDifference(didObserveA, [.init(date: .init(3), data: data2)]) - XCTAssertNoDifference(didObserveB, [.init(date: .init(3), data: data2)]) + XCTAssertNoDifference(actions, [ + .didObserve("B", .init(date: .init(3), data: data2)), + .didSaveFile(path, data2), + ]) + actions = [] now = .init(4) - didObserveA = [] - didObserveB = [] - observerA.cancel() - storage.remove() + try storage.remove() - XCTAssertNoDifference(didObserveA, []) - XCTAssertNoDifference(didObserveB, [nil]) + XCTAssertNoDifference(actions, [ + .didObserve("B", nil), + .didRemoveItem(path), + ]) + actions = [] now = .init(5) - didObserveA = [] - didObserveB = [] observerB.cancel() let data3 = "data-3".data(using: .utf8)! - storage.store(data3) + try storage.store(data3) - XCTAssertNoDifference(didObserveA, []) - XCTAssertNoDifference(didObserveB, []) + XCTAssertNoDifference(actions, [ + .didSaveFile(path, data3), + ]) } } @@ -68,3 +103,11 @@ private extension Date { self.init(timeIntervalSince1970: timeIntervalSince1970) } } + +private enum Action: Equatable { + case didLoadFile(String) + case didGetModifiedTime(String) + case didObserve(String, BackupStorage.Backup?) + case didSaveFile(String, Data) + case didRemoveItem(String) +} -- GitLab