summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2023-04-27 14:55:18 +0200
committerAndrej Mihajlov <and@mullvad.net>2023-04-28 16:45:21 +0200
commitd288c8742cc36d87edb5f3042130ee2633a20349 (patch)
tree4b2ab3341dbe97539a0c518f874ae6a2dc7b3c91
parent5fe9d9b3a459e8deaded1d7a41b511d979ef5ff9 (diff)
downloadmullvadvpn-d288c8742cc36d87edb5f3042130ee2633a20349.tar.xz
mullvadvpn-d288c8742cc36d87edb5f3042130ee2633a20349.zip
TunnelManager: add helper to simulate account expiration
-rw-r--r--ios/MullvadVPN/SettingsManager/TunnelSettingsV2.swift13
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelManager.swift87
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