diff options
| author | Steffen Ernst <steffen.ernst@mullvad.net> | 2025-02-13 10:22:54 +0100 |
|---|---|---|
| committer | Bug Magnet <marco.nikic@mullvad.net> | 2025-02-18 11:52:06 +0100 |
| commit | e61ff5cbaeab56efe2031e633dcfba4d7a00946a (patch) | |
| tree | 09d5d7744bff10bd74d00b864612ec5406e7e91d | |
| parent | 19e8b5d5b9fc38510a5c9287fd9ed8548f4f960c (diff) | |
| download | mullvadvpn-e61ff5cbaeab56efe2031e633dcfba4d7a00946a.tar.xz mullvadvpn-e61ff5cbaeab56efe2031e633dcfba4d7a00946a.zip | |
Add tests for reconnection strategy
5 files changed, 126 insertions, 7 deletions
diff --git a/ios/MullvadSettings/TunnelSettingsStrategy.swift b/ios/MullvadSettings/TunnelSettingsStrategy.swift index 6c8ff01955..8f9cc0bf46 100644 --- a/ios/MullvadSettings/TunnelSettingsStrategy.swift +++ b/ios/MullvadSettings/TunnelSettingsStrategy.swift @@ -22,7 +22,10 @@ public struct TunnelSettingsStrategy: TunnelSettingsStrategyProtocol, Sendable { oldSettings: LatestTunnelSettings, newSettings: LatestTunnelSettings ) -> Bool { - getReconnectionStrategy(oldSettings: oldSettings, newSettings: newSettings) != .noReconnect + getReconnectionStrategy( + oldSettings: oldSettings, + newSettings: newSettings + ) != .currentRelayReconnect } public func getReconnectionStrategy( @@ -35,16 +38,16 @@ public struct TunnelSettingsStrategy: TunnelSettingsStrategyProtocol, Sendable { } switch (oldSettings, newSettings) { case let (old, new) where old != new: - return .softReconnect + return .newRelayReconnect default: - return .noReconnect + return .currentRelayReconnect } } } public enum TunnelSettingsReconnectionStrategy { - case noReconnect - case softReconnect + case currentRelayReconnect + case newRelayReconnect // This will fully disconnect and start a new connection // Attention: This will leak traffic!!! case hardReconnect diff --git a/ios/MullvadVPN/TunnelManager/TunnelManager.swift b/ios/MullvadVPN/TunnelManager/TunnelManager.swift index d12be3b424..ad6deeb3d7 100644 --- a/ios/MullvadVPN/TunnelManager/TunnelManager.swift +++ b/ios/MullvadVPN/TunnelManager/TunnelManager.swift @@ -976,9 +976,9 @@ final class TunnelManager: StorePaymentObserver, @unchecked Sendable { newSettings: updatedSettings ) switch reconnectionStrategy { - case .noReconnect: + case .currentRelayReconnect: self.reconnectTunnel(selectNewRelay: false) - case .softReconnect: + case .newRelayReconnect: self.reconnectTunnel(selectNewRelay: true) case .hardReconnect: self.reapplyTunnelConfiguration() diff --git a/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift b/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift index d123c7026e..246da1b07b 100644 --- a/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift +++ b/ios/MullvadVPNTests/MullvadSettings/TunnelSettingsUpdateTests.swift @@ -101,4 +101,32 @@ final class TunnelSettingsUpdateTests: XCTestCase { // Then: XCTAssertEqual(settings.daita, daitaSettings) } + + func testApplyIAN() { + // Given: + let includeAllNetworks = true + var settings = LatestTunnelSettings() + + // When: + let update = TunnelSettingsUpdate.includeAllNetworks(includeAllNetworks) + update.apply(to: &settings) + + // Then: + XCTAssertEqual(settings.includeAllNetworks, includeAllNetworks) + } + + func testApplyLocalNetworkSharing() { + // Given: + let localNetworkSharing = true + var settings = LatestTunnelSettings() + + // When: + let update = TunnelSettingsUpdate.localNetworkSharing( + localNetworkSharing + ) + update.apply(to: &settings) + + // Then: + XCTAssertEqual(settings.localNetworkSharing, localNetworkSharing) + } } diff --git a/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift b/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift index c06026e92f..0c21fdacc6 100644 --- a/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift +++ b/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift @@ -187,4 +187,66 @@ class TunnelManagerTests: XCTestCase { enforceOrder: true ) } + + /// This test verifies tunnel gets disconnected and reconnected on config reapply. + func testReapplyingConfigDisconnectsAndReconnects() async throws { + var connectedExpectation = expectation(description: "Connected!") + let disconnectedExpectation = expectation(description: "Disconnected!") + + accountProxy.createAccountResult = .success(REST.NewAccountData.mockValue()) + + let relaySelector = RelaySelectorStub { _ in + try RelaySelectorStub.nonFallible().selectRelays( + tunnelSettings: LatestTunnelSettings(), + connectionAttemptCount: 0 + ) + } + + let tunnelManager = TunnelManager( + backgroundTaskProvider: application, + tunnelStore: TunnelStore(application: application), + relayCacheTracker: relayCacheTracker, + accountsProxy: accountProxy, + devicesProxy: devicesProxy, + apiProxy: apiProxy, + accessTokenManager: accessTokenManager, + relaySelector: relaySelector + ) + + let simulatorTunnelProviderHost = SimulatorTunnelProviderHost( + relaySelector: relaySelector, + transportProvider: transportProvider + ) + SimulatorTunnelProvider.shared.delegate = simulatorTunnelProviderHost + let tunnelObserver = TunnelBlockObserver( + didUpdateTunnelStatus: { _, tunnelStatus in + switch tunnelStatus.state { + case .connected: + connectedExpectation.fulfill() + case .disconnected: + disconnectedExpectation.fulfill() + default: + return + } + } + ) + + self.tunnelObserver = tunnelObserver + tunnelManager.addObserver(tunnelObserver) + + _ = try await tunnelManager.setNewAccount() + + XCTAssertTrue(tunnelManager.deviceState.isLoggedIn) + + tunnelManager.startTunnel() + await fulfillment(of: [connectedExpectation]) + tunnelManager + .reapplyTunnelConfiguration() + connectedExpectation = expectation(description: "Connected!") + await fulfillment( + of: [disconnectedExpectation, connectedExpectation], + timeout: .UnitTest.timeout, + enforceOrder: true + ) + } } diff --git a/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelSettingsStrategyTests.swift b/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelSettingsStrategyTests.swift index aec327473e..4b845e724d 100644 --- a/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelSettingsStrategyTests.swift +++ b/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelSettingsStrategyTests.swift @@ -104,4 +104,30 @@ final class TunnelSettingsStrategyTests: XCTestCase { newSettings: updatedSettings )) } + + func testHardReconnectWhenIncludeAllNetworksChange() { + let currentSettings = LatestTunnelSettings() + var updatedSettings = currentSettings + TunnelSettingsUpdate.includeAllNetworks(true) + .apply(to: &updatedSettings) + + let tunnelSettingsStrategy = TunnelSettingsStrategy() + XCTAssertEqual(tunnelSettingsStrategy.getReconnectionStrategy( + oldSettings: currentSettings, + newSettings: updatedSettings + ), .hardReconnect) + } + + func testHardReconnectWhenLocalNetworkSharingChange() { + let currentSettings = LatestTunnelSettings() + var updatedSettings = currentSettings + TunnelSettingsUpdate.localNetworkSharing(true) + .apply(to: &updatedSettings) + + let tunnelSettingsStrategy = TunnelSettingsStrategy() + XCTAssertEqual(tunnelSettingsStrategy.getReconnectionStrategy( + oldSettings: currentSettings, + newSettings: updatedSettings + ), .hardReconnect) + } } |
