Skip to content
Snippets Groups Projects
Commit c2c18618 authored by Dariusz Rybicki's avatar Dariusz Rybicki
Browse files

Create BackupStorage.onDisk implementation

parent e22c3daf
No related branches found
No related tags found
2 merge requests!110Backup improvements & example,!102Release 1.0.0
......@@ -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)
}
)
}
......
......@@ -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)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment