summaryrefslogtreecommitdiffhomepage
path: root/ios
diff options
context:
space:
mode:
authorAndrew Bulhak <andrew.bulhak@mullvad.net>2024-05-24 15:38:17 +0200
committerBug Magnet <marco.nikic@mullvad.net>2024-05-29 13:40:11 +0200
commit12ad692b7f423b9fa1474b14bf4ce6ed5bf4cc91 (patch)
tree8004c16dd018b37827ab7d438a4245de9743f799 /ios
parent002cc53666ce68ebfe6477bf760f4e7c6f603347 (diff)
downloadmullvadvpn-12ad692b7f423b9fa1474b14bf4ce6ed5bf4cc91.tar.xz
mullvadvpn-12ad692b7f423b9fa1474b14bf4ce6ed5bf4cc91.zip
Add tests for Reducer
Diffstat (limited to 'ios')
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj12
-rw-r--r--ios/MullvadVPNTests/MullvadVPN/PacketTunnelCore/PacketTunnelActorReducerTests.swift330
2 files changed, 342 insertions, 0 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index ca03deb050..ef3edd54f1 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -45,6 +45,7 @@
44B02E3B2BC5732D008EDF34 /* LoggingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44B02E3A2BC5732D008EDF34 /* LoggingTests.swift */; };
44B02E3C2BC5B8A5008EDF34 /* Bundle+ProductVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5891BF1B25E3E3EB006D6FB0 /* Bundle+ProductVersion.swift */; };
44B3C43A2BFE2C800079782C /* PacketTunnelActorReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44B3C4392BFE2C800079782C /* PacketTunnelActorReducer.swift */; };
+ 44B3C43D2C00CBBD0079782C /* PacketTunnelActorReducerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44B3C43C2C00CBBC0079782C /* PacketTunnelActorReducerTests.swift */; };
44BB5F972BE527F4002520EB /* TunnelState+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44BB5F962BE527F4002520EB /* TunnelState+UI.swift */; };
44BB5F982BE527F4002520EB /* TunnelState+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44BB5F962BE527F4002520EB /* TunnelState+UI.swift */; };
44DD7D242B6CFFD70005F67F /* StartTunnelOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44DD7D232B6CFFD70005F67F /* StartTunnelOperationTests.swift */; };
@@ -1404,6 +1405,7 @@
449EBA252B975B9700DFA4EB /* PostQuantumKeyReceiving.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostQuantumKeyReceiving.swift; sourceTree = "<group>"; };
44B02E3A2BC5732D008EDF34 /* LoggingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoggingTests.swift; sourceTree = "<group>"; };
44B3C4392BFE2C800079782C /* PacketTunnelActorReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelActorReducer.swift; sourceTree = "<group>"; };
+ 44B3C43C2C00CBBC0079782C /* PacketTunnelActorReducerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PacketTunnelActorReducerTests.swift; sourceTree = "<group>"; };
44BB5F962BE527F4002520EB /* TunnelState+UI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TunnelState+UI.swift"; sourceTree = "<group>"; };
44BB5F992BE529FE002520EB /* TunnelStateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelStateTests.swift; sourceTree = "<group>"; };
44DD7D232B6CFFD70005F67F /* StartTunnelOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartTunnelOperationTests.swift; sourceTree = "<group>"; };
@@ -2383,6 +2385,7 @@
440E9EFB2BDA97C600B1FD11 /* GeneralAPIs */,
440E9EF12BDA940500B1FD11 /* Notifications */,
440E9EF72BDA95AC00B1FD11 /* PacketTunnel */,
+ 44B3C43B2C00CB570079782C /* PacketTunnelCore */,
440E9F012BDA99FA00B1FD11 /* Protocols */,
440E9EFE2BDA991200B1FD11 /* RelayCacheTracker */,
440E9EFF2BDA995800B1FD11 /* TunnelManager */,
@@ -2570,6 +2573,14 @@
path = Protocols;
sourceTree = "<group>";
};
+ 44B3C43B2C00CB570079782C /* PacketTunnelCore */ = {
+ isa = PBXGroup;
+ children = (
+ 44B3C43C2C00CBBC0079782C /* PacketTunnelActorReducerTests.swift */,
+ );
+ path = PacketTunnelCore;
+ sourceTree = "<group>";
+ };
5802EBC32A8E447000E5CE4C /* Router */ = {
isa = PBXGroup;
children = (
@@ -5289,6 +5300,7 @@
A9A5F9EA2ACB05160083449F /* Bundle+ProductVersion.swift in Sources */,
A9A5F9EB2ACB05160083449F /* CharacterSet+IPAddress.swift in Sources */,
F0D8825C2B04F70E00D3EF9A /* OutgoingConnectionData.swift in Sources */,
+ 44B3C43D2C00CBBD0079782C /* PacketTunnelActorReducerTests.swift in Sources */,
A9A5F9EC2ACB05160083449F /* CodingErrors+CustomErrorDescription.swift in Sources */,
A9A5F9ED2ACB05160083449F /* NSRegularExpression+IPAddress.swift in Sources */,
A9A5F9EE2ACB05160083449F /* RESTCreateApplePaymentResponse+Localization.swift in Sources */,
diff --git a/ios/MullvadVPNTests/MullvadVPN/PacketTunnelCore/PacketTunnelActorReducerTests.swift b/ios/MullvadVPNTests/MullvadVPN/PacketTunnelCore/PacketTunnelActorReducerTests.swift
new file mode 100644
index 0000000000..67c26730d2
--- /dev/null
+++ b/ios/MullvadVPNTests/MullvadVPN/PacketTunnelCore/PacketTunnelActorReducerTests.swift
@@ -0,0 +1,330 @@
+//
+// PacketTunnelActorReducerTests.swift
+// MullvadVPNTests
+//
+// Created by Andrew Bulhak on 2024-04-29.
+// Copyright © 2024 Mullvad VPN AB. All rights reserved.
+//
+
+import MullvadTypes
+@testable import PacketTunnelCore
+import WireGuardKitTypes
+import XCTest
+
+final class PacketTunnelActorReducerTests: XCTestCase {
+ // test data
+ let selectedRelay = SelectedRelay(
+ endpoint: MullvadEndpoint(
+ ipv4Relay: IPv4Endpoint(ip: .loopback, port: 1300),
+ ipv4Gateway: .loopback,
+ ipv6Gateway: .loopback,
+ publicKey: PrivateKey().publicKey.rawValue
+ ),
+ hostname: "se-got",
+ location: Location(
+ country: "",
+ countryCode: "se",
+ city: "",
+ cityCode: "got",
+ latitude: 0,
+ longitude: 0
+ ), retryAttempts: 0
+ )
+ func makeConnectionData(keyPolicy: State.KeyPolicy = .useCurrent) -> State.ConnectionData {
+ State.ConnectionData(
+ selectedRelay: selectedRelay,
+ relayConstraints: RelayConstraints(),
+ keyPolicy: keyPolicy,
+ networkReachability: .reachable,
+ connectionAttemptCount: 0,
+ connectedEndpoint: selectedRelay.endpoint,
+ transportLayer: .udp,
+ remotePort: 12345,
+ isPostQuantum: false
+ )
+ }
+
+ // MARK: .start
+
+ func testHandleStartWithoutPreselectedRelay() {
+ // Given
+ var state = State.initial
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .start(StartOptions(launchSource: .app)))
+ // Then
+ XCTAssertEqual(effects, [
+ .startDefaultPathObserver,
+ .startTunnelMonitor,
+ .startConnection(.random),
+ ])
+ }
+
+ func testHandleStartWithPreselectedRelay() {
+ // Given
+ var state = State.initial
+ // When
+ let effects = PacketTunnelActor.reducer(
+ &state,
+ .start(StartOptions(launchSource: .app, selectedRelay: selectedRelay))
+ )
+ // Then
+ XCTAssertEqual(effects, [
+ .startDefaultPathObserver,
+ .startTunnelMonitor,
+ .startConnection(.preSelected(selectedRelay)),
+ ])
+ }
+
+ // MARK: .stop
+
+ func testHandleStopFromConnected() {
+ // Given
+ let connectionData = makeConnectionData()
+ var state = State.connected(connectionData)
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .stop)
+ // Then
+ XCTAssertEqual(state, .disconnecting(connectionData))
+ XCTAssertEqual(effects, [
+ .stopTunnelMonitor,
+ .stopDefaultPathObserver,
+ .stopTunnelAdapter,
+ .setDisconnectedState,
+ ])
+ }
+
+ func testHandleStopFromConnecting() {
+ // Given
+ let connectionData = makeConnectionData()
+ var state = State.connecting(connectionData)
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .stop)
+ // Then
+ XCTAssertEqual(state, .disconnecting(connectionData))
+ XCTAssertEqual(effects, [
+ .stopTunnelMonitor,
+ .stopDefaultPathObserver,
+ .stopTunnelAdapter,
+ .setDisconnectedState,
+ ])
+ }
+
+ func testHandleStopFromReconnecting() {
+ // Given
+ let connectionData = makeConnectionData()
+ var state = State.reconnecting(connectionData)
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .stop)
+ // Then
+ XCTAssertEqual(state, .disconnecting(connectionData))
+ XCTAssertEqual(effects, [
+ .stopTunnelMonitor,
+ .stopDefaultPathObserver,
+ .stopTunnelAdapter,
+ .setDisconnectedState,
+ ])
+ }
+
+ func testHandleStopFromError() {
+ // Given
+ let blockingData = State.BlockingData(
+ reason: .accountExpired,
+ keyPolicy: .useCurrent,
+ networkReachability: .reachable,
+ priorState: .connected
+ )
+ var state = State.error(blockingData)
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .stop)
+
+ // Then
+ XCTAssertEqual(effects, [
+ .stopDefaultPathObserver,
+ .stopTunnelAdapter,
+ .setDisconnectedState,
+ ])
+ }
+
+ func testHandleStopFromUnconnectedStates() {
+ // Given
+ let states: [State] = [.initial, .disconnected]
+
+ for var state in states {
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .stop)
+
+ // Then
+ XCTAssertEqual(effects, [])
+ }
+ }
+
+ // MARK: .reconnect
+
+ func testHandleUserInitiatedReconnectFromConnectedStates() {
+ // Given
+ var state = State.connected(makeConnectionData())
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .reconnect(.current, reason: .userInitiated))
+
+ // Then
+ XCTAssertEqual(effects, [
+ .stopTunnelMonitor,
+ .restartConnection(.current, .userInitiated),
+ ])
+ }
+
+ func testHandleConnectionLossReconnectFromConnectedStates() {
+ // Given
+ var state = State.connected(makeConnectionData())
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .reconnect(.random, reason: .connectionLoss))
+
+ // Then
+ XCTAssertEqual(effects, [
+ .restartConnection(.random, .connectionLoss),
+ ])
+ }
+
+ func testHandleReconnectFromDisconnectedIsNoOp() {
+ // Given
+ var state = State.disconnected
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .reconnect(.random, reason: .connectionLoss))
+
+ // Then
+ XCTAssertEqual(effects, [])
+ }
+
+ func testHandleConnectionLossReconnectFromPQKeyNegotiation() {
+ // Given
+ var state = State.negotiatingPostQuantumKey(makeConnectionData(), PrivateKey())
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .reconnect(.random, reason: .connectionLoss))
+
+ // Then
+ XCTAssertEqual(effects, [.restartConnection(.random, .connectionLoss)])
+ }
+
+ func testHandleUserReconnectFromPQKeyNegotiation() {
+ // Given
+ var state = State.negotiatingPostQuantumKey(makeConnectionData(), PrivateKey())
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .reconnect(.random, reason: .userInitiated))
+
+ // Then
+ XCTAssertEqual(effects, [
+ .stopTunnelMonitor,
+ .restartConnection(.random, .userInitiated),
+ ])
+ }
+
+ // MARK: .error
+
+ func testHandleError() {
+ // Given
+ var state = State.connected(makeConnectionData())
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .error(.deviceRevoked))
+
+ // then
+ XCTAssertEqual(effects, [
+ .configureForErrorState(.deviceRevoked),
+ ])
+ }
+
+ // MARK: .notifyKeyRotated
+
+ func testHandleNotifyKeyRotatedWhileUsingCurrentKey() {
+ // Given
+ var state = State.connected(makeConnectionData(keyPolicy: .useCurrent))
+ let date = Date()
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .notifyKeyRotated(date))
+
+ // then
+ XCTAssertEqual(effects, [
+ .cacheActiveKey(date),
+ ])
+ }
+
+ func testHandleNotifyKeyRotatedWhileUsingPriorKey() {
+ // Given
+ let keyPolicy = State.KeyPolicy.usePrior(PrivateKey(), AutoCancellingTask(Task(operation: {})))
+ var state = State.connected(makeConnectionData(keyPolicy: keyPolicy))
+ let date = Date()
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .notifyKeyRotated(date))
+
+ // then
+ XCTAssertEqual(effects, [])
+ }
+
+ // MARK: .switchKey
+
+ func testHandleSwitchKeyFromUseCurrent() {
+ // Given
+ var state = State.connected(makeConnectionData(keyPolicy: .useCurrent))
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .switchKey)
+
+ // then
+ XCTAssertEqual(effects, [])
+ }
+
+ func testHandleSwitchKeyFromUsePrior() {
+ // Given
+ let keyPolicy = State.KeyPolicy.usePrior(PrivateKey(), AutoCancellingTask(Task(operation: {})))
+ var state = State.connected(makeConnectionData(keyPolicy: keyPolicy))
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .switchKey)
+
+ // then
+ XCTAssertEqual(state.keyPolicy, State.KeyPolicy.useCurrent)
+ XCTAssertEqual(effects, [
+ .reconnect(.random),
+ ])
+ }
+
+ // MARK: .monitorEvent
+
+ func testHandleMonitorEvent_ConnectionEstablishedWhileConnecting() {
+ // Given
+ var connectionData = makeConnectionData()
+ connectionData.connectionAttemptCount = 2
+ var state = State.connecting(connectionData)
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .monitorEvent(.connectionEstablished))
+
+ // Then
+ var expectedConnectionData = connectionData
+ expectedConnectionData.connectionAttemptCount = 0
+ XCTAssertEqual(state, .connected(expectedConnectionData))
+ XCTAssertEqual(effects, [])
+ }
+
+ func testHandleMonitorEvent_ConnectionLostWhileConnected() {
+ // Given
+ let connectionData = makeConnectionData()
+ var state = State.connected(connectionData)
+
+ // When
+ let effects = PacketTunnelActor.reducer(&state, .monitorEvent(.connectionLost))
+
+ // Then
+ XCTAssertEqual(effects, [
+ .restartConnection(.random, .connectionLoss),
+ ])
+ }
+}