diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2023-04-27 14:55:18 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2023-04-28 16:45:21 +0200 |
| commit | d288c8742cc36d87edb5f3042130ee2633a20349 (patch) | |
| tree | 4b2ab3341dbe97539a0c518f874ae6a2dc7b3c91 | |
| parent | 5fe9d9b3a459e8deaded1d7a41b511d979ef5ff9 (diff) | |
| download | mullvadvpn-d288c8742cc36d87edb5f3042130ee2633a20349.tar.xz mullvadvpn-d288c8742cc36d87edb5f3042130ee2633a20349.zip | |
TunnelManager: add helper to simulate account expiration
| -rw-r--r-- | ios/MullvadVPN/SettingsManager/TunnelSettingsV2.swift | 13 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/TunnelManager.swift | 87 |
2 files changed, 100 insertions, 0 deletions
diff --git a/ios/MullvadVPN/SettingsManager/TunnelSettingsV2.swift b/ios/MullvadVPN/SettingsManager/TunnelSettingsV2.swift index b9dca0bf21..7ee39c6934 100644 --- a/ios/MullvadVPN/SettingsManager/TunnelSettingsV2.swift +++ b/ios/MullvadVPN/SettingsManager/TunnelSettingsV2.swift @@ -85,6 +85,19 @@ enum DeviceState: Codable, Equatable { return nil } } + + /** + Mutates account and device data when in logged in state, otherwise does nothing. + */ + mutating func updateData(_ body: (inout StoredAccountData, inout StoredDeviceData) -> Void) { + switch self { + case var .loggedIn(accountData, deviceData): + body(&accountData, &deviceData) + self = .loggedIn(accountData, deviceData) + case .revoked, .loggedOut: + break + } + } } struct StoredDeviceData: Codable, Equatable { diff --git a/ios/MullvadVPN/TunnelManager/TunnelManager.swift b/ios/MullvadVPN/TunnelManager/TunnelManager.swift index 09b1c10641..9c9190200b 100644 --- a/ios/MullvadVPN/TunnelManager/TunnelManager.swift +++ b/ios/MullvadVPN/TunnelManager/TunnelManager.swift @@ -960,6 +960,93 @@ final class TunnelManager: StorePaymentObserver { } } +#if DEBUG + +// MARK: - Simulations + +extension TunnelManager { + enum AccountExpirySimulationOption { + case closeToExpiry + case expired + case active + + fileprivate var date: Date? { + let calendar = Calendar.current + let now = Date() + + switch self { + case .active: + return calendar.date(byAdding: .year, value: 1, to: now) + + case .closeToExpiry: + return calendar.date( + byAdding: DateComponents(day: NotificationConfiguration.closeToExpiryTriggerInterval, second: 5), + to: now + ) + + case .expired: + return calendar.date(byAdding: .minute, value: -1, to: now) + } + } + } + + /** + + This function simulates account state transitions. The change is not permanent and any call to + `updateAccountData()` will overwrite it, but it's usually enough for quick testing. + + It can be invoked somewhere in `initTunnelManagerOperation` (`AppDelegate`) after tunnel manager is fully + initialized. The following code snippet can be used to cycle through various states: + + ``` + func delay(seconds: UInt) async throws { + try await Task.sleep(nanoseconds: UInt64(seconds) * 1_000_000_000) + } + + Task { + print("Wait 5 seconds") + try await delay(seconds: 5) + + print("Simulate active account") + self.tunnelManager.simulateAccountExpiration(option: .active) + try await delay(seconds: 5) + + print("Simulate close to expiry") + self.tunnelManager.simulateAccountExpiration(option: .closeToExpiry) + try await delay(seconds: 10) + + print("Simulate expired account") + self.tunnelManager.simulateAccountExpiration(option: .expired) + try await delay(seconds: 5) + + print("Simulate active account") + self.tunnelManager.simulateAccountExpiration(option: .active) + } + ``` + + Another way to invoke this code is to pause debugger and run it directly: + + ``` + command alias swift expression -l Swift -O -- + + swift import MullvadVPN + swift (UIApplication.shared.delegate as? AppDelegate)?.tunnelManager.simulateAccountExpiration(option: .closeToExpiry) + ``` + + */ + func simulateAccountExpiration(option: AccountExpirySimulationOption) { + scheduleDeviceStateUpdate(taskName: "Simulating account expiry", reconnectTunnel: false) { deviceState in + deviceState.updateData { accountData, deviceData in + guard let date = option.date else { return } + + accountData.expiry = date + } + } + } +} + +#endif + private struct TunnelInteractorProxy: TunnelInteractor { private let tunnelManager: TunnelManager |
