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

Merge branch 'fix/example-save-facts-when-restored' into 'development'

Backup restoration fixes

See merge request elixxir/elixxir-dapps-sdk-swift!105
parents 394c8fc6 58f851c4
No related branches found
No related tags found
2 merge requests!105Backup restoration fixes,!102Release 1.0.0
This commit is part of merge request !102. Comments created here will be created in the context of that merge request.
......@@ -274,8 +274,10 @@ let package = Package(
.target(
name: "RestoreFeature",
dependencies: [
.target(name: "AppCore"),
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
.product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
.product(name: "XXModels", package: "client-ios-db"),
],
swiftSettings: swiftSettings
),
......
......@@ -103,7 +103,9 @@ extension AppEnvironment {
restore: {
RestoreEnvironment(
messenger: messenger,
db: dbManager.getDB,
loadData: .live,
now: Date.init,
mainQueue: mainQueue,
bgQueue: bgQueue
)
......
import AppCore
import Combine
import ComposableArchitecture
import Foundation
import XCTestDynamicOverlay
import XXMessengerClient
import XXModels
public struct RestoreState: Equatable {
public enum Field: String, Hashable {
......@@ -58,18 +60,24 @@ public enum RestoreAction: Equatable, BindableAction {
public struct RestoreEnvironment {
public init(
messenger: Messenger,
db: DBManagerGetDB,
loadData: URLDataLoader,
now: @escaping () -> Date,
mainQueue: AnySchedulerOf<DispatchQueue>,
bgQueue: AnySchedulerOf<DispatchQueue>
) {
self.messenger = messenger
self.db = db
self.loadData = loadData
self.now = now
self.mainQueue = mainQueue
self.bgQueue = bgQueue
}
public var messenger: Messenger
public var db: DBManagerGetDB
public var loadData: URLDataLoader
public var now: () -> Date
public var mainQueue: AnySchedulerOf<DispatchQueue>
public var bgQueue: AnySchedulerOf<DispatchQueue>
}
......@@ -77,7 +85,9 @@ public struct RestoreEnvironment {
extension RestoreEnvironment {
public static let unimplemented = RestoreEnvironment(
messenger: .unimplemented,
db: .unimplemented,
loadData: .unimplemented,
now: XCTUnimplemented("\(Self.self).now"),
mainQueue: .unimplemented,
bgQueue: .unimplemented
)
......@@ -118,12 +128,20 @@ public let restoreReducer = Reducer<RestoreState, RestoreAction, RestoreEnvironm
state.restoreFailure = nil
return Effect.result {
do {
_ = try env.messenger.restoreBackup(
let result = try env.messenger.restoreBackup(
backupData: backupData,
backupPassphrase: backupPassphrase
)
try env.db().saveContact(Contact(
id: try env.messenger.e2e.tryGet().getContact().getId(),
username: result.restoredParams.username,
email: result.restoredParams.email,
phone: result.restoredParams.phone,
createdAt: env.now()
))
return .success(.finished)
} catch {
try? env.messenger.destroy()
return .success(.failed(error as NSError))
}
}
......
import CustomDump
import ComposableArchitecture
import CustomDump
import XCTest
@testable import RestoreFeature
import XXClient
import XXMessengerClient
import XXModels
@testable import RestoreFeature
final class RestoreFeatureTests: XCTestCase {
func testFileImport() {
......@@ -79,15 +81,18 @@ final class RestoreFeatureTests: XCTestCase {
let backupPassphrase = "backup-passphrase"
let restoreResult = MessengerRestoreBackup.Result(
restoredParams: BackupParams.init(
username: "",
email: nil,
phone: nil
username: "restored-username",
email: "restored-email",
phone: "restored-phone"
),
restoredContacts: []
)
let now = Date()
let contactId = "contact-id".data(using: .utf8)!
var didRestoreWithData: [Data] = []
var didRestoreWithPassphrase: [String] = []
var didSaveContact: [XXModels.Contact] = []
let store = TestStore(
initialState: RestoreState(
......@@ -99,11 +104,29 @@ final class RestoreFeatureTests: XCTestCase {
store.environment.bgQueue = .immediate
store.environment.mainQueue = .immediate
store.environment.now = { now }
store.environment.messenger.restoreBackup.run = { data, passphrase in
didRestoreWithData.append(data)
didRestoreWithPassphrase.append(passphrase)
return restoreResult
}
store.environment.messenger.e2e.get = {
var e2e: E2E = .unimplemented
e2e.getContact.run = {
var contact: XXClient.Contact = .unimplemented(Data())
contact.getIdFromContact.run = { _ in contactId }
return contact
}
return e2e
}
store.environment.db.run = {
var db: Database = .unimplemented
db.saveContact.run = { contact in
didSaveContact.append(contact)
return contact
}
return db
}
store.send(.set(\.$passphrase, backupPassphrase)) {
$0.passphrase = backupPassphrase
......@@ -115,6 +138,13 @@ final class RestoreFeatureTests: XCTestCase {
XCTAssertNoDifference(didRestoreWithData, [backupData])
XCTAssertNoDifference(didRestoreWithPassphrase, [backupPassphrase])
XCTAssertNoDifference(didSaveContact, [Contact(
id: contactId,
username: restoreResult.restoredParams.username,
email: restoreResult.restoredParams.email,
phone: restoreResult.restoredParams.phone,
createdAt: now
)])
store.receive(.finished) {
$0.isRestoring = false
......@@ -137,6 +167,8 @@ final class RestoreFeatureTests: XCTestCase {
struct Failure: Error {}
let failure = Failure()
var didDestroyMessenger = 0
let store = TestStore(
initialState: RestoreState(
file: .init(name: "name", data: "data".data(using: .utf8)!)
......@@ -148,11 +180,14 @@ final class RestoreFeatureTests: XCTestCase {
store.environment.bgQueue = .immediate
store.environment.mainQueue = .immediate
store.environment.messenger.restoreBackup.run = { _, _ in throw failure }
store.environment.messenger.destroy.run = { didDestroyMessenger += 1 }
store.send(.restoreTapped) {
$0.isRestoring = true
}
XCTAssertEqual(didDestroyMessenger, 1)
store.receive(.failed(failure as NSError)) {
$0.isRestoring = false
$0.restoreFailure = failure.localizedDescription
......
......@@ -2,13 +2,9 @@
import PackageDescription
let swiftSettings: [SwiftSetting] = [
.unsafeFlags(
[
"-Xfrontend", "-debug-time-function-bodies",
"-Xfrontend", "-debug-time-expression-type-checking",
],
.when(configuration: .debug)
),
//.unsafeFlags(["-Xfrontend", "-warn-concurrency"], .when(configuration: .debug)),
//.unsafeFlags(["-Xfrontend", "-debug-time-function-bodies"], .when(configuration: .debug)),
//.unsafeFlags(["-Xfrontend", "-debug-time-expression-type-checking"], .when(configuration: .debug)),
]
let package = Package(
......
......@@ -30,7 +30,6 @@ extension MessengerRestoreBackup {
public static func live(_ env: MessengerEnvironment) -> MessengerRestoreBackup {
MessengerRestoreBackup { backupData, backupPassphrase in
let storageDir = env.storageDir
do {
let ndfData = try env.downloadNDF(env.ndfEnvironment)
let password = env.generateSecret()
try env.passwordStorage.save(password)
......@@ -48,6 +47,7 @@ extension MessengerRestoreBackup {
password: password,
cMixParamsJSON: env.getCMixParams()
)
env.cMix.set(cMix)
try cMix.startNetworkFollower(timeoutMS: 30_000)
let e2e = try env.login(
cMixId: cMix.getId(),
......@@ -55,6 +55,8 @@ extension MessengerRestoreBackup {
identity: try cMix.makeReceptionIdentity(legacy: true),
e2eParamsJSON: env.getE2EParams()
)
env.e2e.set(e2e)
env.isListeningForMessages.set(false)
let decoder = JSONDecoder()
let paramsData = report.params.data(using: .utf8)!
let params = try decoder.decode(BackupParams.self, from: paramsData)
......@@ -70,18 +72,11 @@ extension MessengerRestoreBackup {
),
follower: UdNetworkStatus { cMix.networkFollowerStatus() }
)
env.cMix.set(cMix)
env.e2e.set(e2e)
env.ud.set(ud)
env.isListeningForMessages.set(false)
return Result(
restoredParams: params,
restoredContacts: report.restoredContacts
)
} catch {
try? env.fileManager.removeDirectory(storageDir)
throw error
}
}
}
}
......
......@@ -136,6 +136,7 @@ final class MessengerRestoreBackupTests: XCTestCase {
password: password,
cMixParams: cMixParams
),
.didSetCMix,
.cMixDidStartNetworkFollower(
timeoutMS: 30_000
),
......@@ -148,6 +149,10 @@ final class MessengerRestoreBackupTests: XCTestCase {
identity: receptionIdentity,
e2eParamsJSON: e2eParams
),
.didSetE2E,
.didSetIsListeningForMessages(
isListening: false
),
.didNewUdManagerFromBackup(params: .init(
e2eId: e2eId,
username: Fact(type: .username, value: backupParams.username),
......@@ -157,12 +162,7 @@ final class MessengerRestoreBackupTests: XCTestCase {
contact: udContactFromNdf,
address: udAddressFromNdf
)),
.didSetCMix,
.didSetE2E,
.didSetUD,
.didSetIsListeningForMessages(
isListening: false
),
])
XCTAssertNoDifference(result, MessengerRestoreBackup.Result(
......@@ -175,19 +175,13 @@ final class MessengerRestoreBackupTests: XCTestCase {
struct Failure: Error, Equatable {}
let failure = Failure()
var actions: [CaughtAction] = []
var env: MessengerEnvironment = .unimplemented
env.downloadNDF.run = { _ in throw failure }
env.fileManager.removeDirectory = { actions.append(.didRemoveDirectory(path: $0)) }
let restore: MessengerRestoreBackup = .live(env)
XCTAssertThrowsError(try restore(backupData: Data(), backupPassphrase: "")) { error in
XCTAssertNoDifference(error as? Failure, failure)
}
XCTAssertNoDifference(actions, [
.didRemoveDirectory(path: env.storageDir)
])
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment