From 5c13b7e1d4e0b68e71c17873e2de018931f269fa Mon Sep 17 00:00:00 2001 From: Andrej Mihajlov Date: Wed, 11 Oct 2023 17:59:32 +0200 Subject: [PATCH] Hide State and expose Observed State instead --- ios/MullvadVPN.xcodeproj/project.pbxproj | 8 ++ .../PacketTunnelProvider.swift | 2 +- .../Actor/ObservedState+Extensions.swift | 75 ++++++++++++++++++ .../Actor/ObservedState.swift | 78 +++++++++++++++++++ .../Actor/PacketTunnelActor+Extensions.swift | 16 ++-- .../Actor/PacketTunnelActor.swift | 5 +- .../Actor/PacketTunnelActorProtocol.swift | 2 +- .../Actor/State+Extensions.swift | 44 ----------- ios/PacketTunnelCore/Actor/State.swift | 16 ++-- .../IPC/AppMessageHandler.swift | 2 +- .../AppMessageHandlerTests.swift | 2 - .../Mocks/PacketTunnelActorStub.swift | 4 +- .../PacketTunnelActorTests.swift | 36 ++++----- 13 files changed, 201 insertions(+), 89 deletions(-) create mode 100644 ios/PacketTunnelCore/Actor/ObservedState+Extensions.swift create mode 100644 ios/PacketTunnelCore/Actor/ObservedState.swift diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 6484120dbc86..ba0d868cd389 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -161,6 +161,7 @@ 5878F50029CDA742003D4BE2 /* UIView+AutoLayoutBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878F4FF29CDA742003D4BE2 /* UIView+AutoLayoutBuilder.swift */; }; 587988C728A2A01F00E3DF54 /* AccountDataThrottling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587988C628A2A01F00E3DF54 /* AccountDataThrottling.swift */; }; 587A01FC23F1F0BE00B68763 /* SimulatorTunnelProviderHost.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587A01FB23F1F0BE00B68763 /* SimulatorTunnelProviderHost.swift */; }; + 587A5E522ADD7569003A70F1 /* ObservedState+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587A5E512ADD7569003A70F1 /* ObservedState+Extensions.swift */; }; 587B7536266528A200DEF7E9 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587B7535266528A200DEF7E9 /* NotificationManager.swift */; }; 587B753B2666467500DEF7E9 /* NotificationBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587B753A2666467500DEF7E9 /* NotificationBannerView.swift */; }; 587B753D2666468F00DEF7E9 /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587B753C2666468F00DEF7E9 /* NotificationController.swift */; }; @@ -292,6 +293,7 @@ 58CE5E66224146200008646E /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CE5E65224146200008646E /* LoginViewController.swift */; }; 58CE5E6B224146210008646E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 58CE5E6A224146210008646E /* Assets.xcassets */; }; 58CE5E81224146470008646E /* PacketTunnel.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 58CE5E79224146470008646E /* PacketTunnel.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 58CF95A22AD6F35800B59F5D /* ObservedState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CF95A12AD6F35800B59F5D /* ObservedState.swift */; }; 58D0C79E23F1CEBA00FE9BA7 /* SnapshotHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D0C79D23F1CEBA00FE9BA7 /* SnapshotHelper.swift */; }; 58D0C7A223F1CECF00FE9BA7 /* MullvadVPNScreenshots.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D0C7A023F1CECF00FE9BA7 /* MullvadVPNScreenshots.swift */; }; 58D223A8294C8A490029F5F8 /* Operations.h in Headers */ = {isa = PBXBuildFile; fileRef = 58D223A7294C8A490029F5F8 /* Operations.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1315,6 +1317,7 @@ 587988C628A2A01F00E3DF54 /* AccountDataThrottling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDataThrottling.swift; sourceTree = ""; }; 58799A352A84FC9F007BE51F /* PingerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PingerProtocol.swift; sourceTree = ""; }; 587A01FB23F1F0BE00B68763 /* SimulatorTunnelProviderHost.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimulatorTunnelProviderHost.swift; sourceTree = ""; }; + 587A5E512ADD7569003A70F1 /* ObservedState+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ObservedState+Extensions.swift"; sourceTree = ""; }; 587AD7C523421D7000E93A53 /* TunnelSettingsV1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelSettingsV1.swift; sourceTree = ""; }; 587B7535266528A200DEF7E9 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; 587B753A2666467500DEF7E9 /* NotificationBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationBannerView.swift; sourceTree = ""; }; @@ -1432,6 +1435,7 @@ 58CE5E79224146470008646E /* PacketTunnel.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = PacketTunnel.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 58CE5E7D224146470008646E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58CE5E7E224146470008646E /* PacketTunnel.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PacketTunnel.entitlements; sourceTree = ""; }; + 58CF95A12AD6F35800B59F5D /* ObservedState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservedState.swift; sourceTree = ""; }; 58D0C79323F1CE7000FE9BA7 /* MullvadVPNScreenshots.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MullvadVPNScreenshots.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58D0C79D23F1CEBA00FE9BA7 /* SnapshotHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnapshotHelper.swift; sourceTree = ""; }; 58D0C79F23F1CECF00FE9BA7 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -2336,6 +2340,8 @@ 5838322A2AC3EF9600EA2071 /* CommandChannel.swift */, 583E60952A9F6D0800DC61EF /* ConfigurationBuilder.swift */, 580D6B892AB31AB400B2D6E0 /* NetworkPath+NetworkReachability.swift */, + 58CF95A12AD6F35800B59F5D /* ObservedState.swift */, + 587A5E512ADD7569003A70F1 /* ObservedState+Extensions.swift */, 58E9C3852A4EF1CB00CFDEAC /* PacketTunnelActor.swift */, 583832242AC318A100EA2071 /* PacketTunnelActor+ConnectionMonitoring.swift */, 583832222AC3181400EA2071 /* PacketTunnelActor+ErrorState.swift */, @@ -4188,12 +4194,14 @@ 58C7A4572A863FB90060C66F /* TunnelDeviceInfoProtocol.swift in Sources */, 58C7A4562A863FB90060C66F /* DefaultPathObserverProtocol.swift in Sources */, 58FE25DA2AA72A8F003D1918 /* PacketTunnelActor.swift in Sources */, + 587A5E522ADD7569003A70F1 /* ObservedState+Extensions.swift in Sources */, 58FE25E62AA738E8003D1918 /* TunnelAdapterProtocol.swift in Sources */, 583832252AC318A100EA2071 /* PacketTunnelActor+ConnectionMonitoring.swift in Sources */, 58C7A4552A863FB90060C66F /* TunnelMonitor.swift in Sources */, 58C7AF182ABD84AB007EDD7A /* ProxyURLResponse.swift in Sources */, 58C7A4512A863FB50060C66F /* PingerProtocol.swift in Sources */, 583832292AC3DF1300EA2071 /* Command.swift in Sources */, + 58CF95A22AD6F35800B59F5D /* ObservedState.swift in Sources */, 583832232AC3181400EA2071 /* PacketTunnelActor+ErrorState.swift in Sources */, 58C7AF112ABD8480007EDD7A /* TunnelProviderMessage.swift in Sources */, 58C7AF162ABD84A8007EDD7A /* URLRequestProxy.swift in Sources */, diff --git a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift index 1c155ca7bc55..cf8ec138f7e3 100644 --- a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift +++ b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift @@ -164,7 +164,7 @@ extension PacketTunnelProvider { stopObservingActorState() stateObserverTask = Task { - let stateStream = await self.actor.states + let stateStream = await self.actor.observedStates var lastConnectionAttempt: UInt = 0 for await newState in stateStream { diff --git a/ios/PacketTunnelCore/Actor/ObservedState+Extensions.swift b/ios/PacketTunnelCore/Actor/ObservedState+Extensions.swift new file mode 100644 index 000000000000..954f4450c520 --- /dev/null +++ b/ios/PacketTunnelCore/Actor/ObservedState+Extensions.swift @@ -0,0 +1,75 @@ +// +// ObservedState+Extensions.swift +// PacketTunnelCore +// +// Created by pronebird on 16/10/2023. +// Copyright © 2023 Mullvad VPN AB. All rights reserved. +// + +import Foundation +import MullvadTypes + +extension ObservedState { + public var packetTunnelStatus: PacketTunnelStatus { + var status = PacketTunnelStatus() + + switch self { + case let .connecting(connState), + let .connected(connState), + let .reconnecting(connState), + let .disconnecting(connState): + switch connState.networkReachability { + case .reachable: + status.isNetworkReachable = true + case .unreachable: + status.isNetworkReachable = false + case .undetermined: + // TODO: fix me + status.isNetworkReachable = true + } + + status.numberOfFailedAttempts = connState.connectionAttemptCount + status.tunnelRelay = connState.selectedRelay.packetTunnelRelay + + case .disconnected, .initial: + break + + case let .error(blockedState): + status.blockedStateReason = blockedState.reason + } + + return status + } + + public var relayConstraints: RelayConstraints? { + switch self { + case let .connecting(connState), let .connected(connState), let .reconnecting(connState): + return connState.relayConstraints + + case let .error(blockedState): + return blockedState.relayConstraints + + case .initial, .disconnecting, .disconnected: + return nil + } + } + + public var name: String { + switch self { + case .connected: + return "Connected" + case .connecting: + return "Connecting" + case .reconnecting: + return "Reconnecting" + case .disconnecting: + return "Disconnecting" + case .disconnected: + return "Disconnected" + case .initial: + return "Initial" + case .error: + return "Error" + } + } +} diff --git a/ios/PacketTunnelCore/Actor/ObservedState.swift b/ios/PacketTunnelCore/Actor/ObservedState.swift new file mode 100644 index 000000000000..bdef36412295 --- /dev/null +++ b/ios/PacketTunnelCore/Actor/ObservedState.swift @@ -0,0 +1,78 @@ +// +// ObservedState.swift +// PacketTunnelCore +// +// Created by pronebird on 11/10/2023. +// Copyright © 2023 Mullvad VPN AB. All rights reserved. +// + +import Combine +import Foundation +import MullvadTypes +import Network + +/// A serializable representation of internal state. +public enum ObservedState: Equatable, Codable { + case initial + case connecting(ObservedConnectionState) + case reconnecting(ObservedConnectionState) + case connected(ObservedConnectionState) + case disconnecting(ObservedConnectionState) + case disconnected + case error(ObservedBlockedState) +} + +/// A serializable representation of internal connection state. +public struct ObservedConnectionState: Equatable, Codable { + public var selectedRelay: SelectedRelay + public var relayConstraints: RelayConstraints + public var networkReachability: NetworkReachability + public var connectionAttemptCount: UInt +} + +/// A serializable representation of internal blocked state. +public struct ObservedBlockedState: Equatable, Codable { + public var reason: BlockedStateReason + public var relayConstraints: RelayConstraints? +} + +extension State { + /// Map `State` to `ObservedState`. + var observedState: ObservedState { + switch self { + case .initial: + return .initial + case let .connecting(connState): + return .connecting(connState.observedConnectionState) + case let .connected(connState): + return .connected(connState.observedConnectionState) + case let .reconnecting(connState): + return .reconnecting(connState.observedConnectionState) + case let .disconnecting(connState): + return .disconnecting(connState.observedConnectionState) + case .disconnected: + return .disconnected + case let .error(blockedState): + return .error(blockedState.observedBlockedState) + } + } +} + +extension ConnectionState { + /// Map `ConnectionState` to `ObservedConnectionState`. + var observedConnectionState: ObservedConnectionState { + ObservedConnectionState( + selectedRelay: selectedRelay, + relayConstraints: relayConstraints, + networkReachability: networkReachability, + connectionAttemptCount: connectionAttemptCount + ) + } +} + +extension BlockedState { + /// Map `BlockedState` to `ObservedBlockedState` + var observedBlockedState: ObservedBlockedState { + return ObservedBlockedState(reason: reason, relayConstraints: relayConstraints) + } +} diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActor+Extensions.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActor+Extensions.swift index 71bd13c057cd..3bd2c5631523 100644 --- a/ios/PacketTunnelCore/Actor/PacketTunnelActor+Extensions.swift +++ b/ios/PacketTunnelCore/Actor/PacketTunnelActor+Extensions.swift @@ -9,11 +9,11 @@ import Foundation extension PacketTunnelActor { - /// Returns a stream yielding new value when `state` changes. - /// The stream starts with current `state` and ends upon moving to `.disconnected` state. - public var states: AsyncStream { + /// Returns a stream yielding `ObservedState`. + /// Note that the stream yields current value when created. + public var observedStates: AsyncStream { AsyncStream { continuation in - let cancellable = self.$state.sink { newState in + let cancellable = $observedState.sink { newState in continuation.yield(newState) // Finish stream once entered `.disconnected` state. @@ -28,10 +28,10 @@ extension PacketTunnelActor { } } - /// Wait until the `state` moved to `.connected`. + /// Wait until the `observedState` moved to `.connected`. /// Should return if the state is `.disconnected` as this is the final state of actor. public func waitUntilConnected() async { - for await newState in states { + for await newState in observedStates { switch newState { case .connected, .disconnected: // Return once either desired or final state is reached. @@ -43,9 +43,9 @@ extension PacketTunnelActor { } } - /// Wait until the `state` moved to `.disiconnected`. + /// Wait until the `observedState` moved to `.disiconnected`. public func waitUntilDisconnected() async { - for await newState in states { + for await newState in observedStates { if case .disconnected = newState { return } diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift index c82b0f8ccbde..8d432ae3d1d2 100644 --- a/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift +++ b/ios/PacketTunnelCore/Actor/PacketTunnelActor.swift @@ -25,12 +25,15 @@ import class WireGuardKitTypes.PrivateKey same anyway. */ public actor PacketTunnelActor { - @Published internal(set) public var state: State = .initial { + var state: State = .initial { didSet { logger.debug("\(state.logFormat())") + observedState = state.observedState } } + @Published internal(set) public var observedState: ObservedState = .initial + let logger = Logger(label: "PacketTunnelActor") let timings: PacketTunnelActorTimings diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActorProtocol.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActorProtocol.swift index d5acf6bae390..749b30713a9b 100644 --- a/ios/PacketTunnelCore/Actor/PacketTunnelActorProtocol.swift +++ b/ios/PacketTunnelCore/Actor/PacketTunnelActorProtocol.swift @@ -9,7 +9,7 @@ import Foundation public protocol PacketTunnelActorProtocol { - var state: State { get async } + var observedState: ObservedState { get async } func reconnect(to nextRelay: NextRelay) func notifyKeyRotation(date: Date?) diff --git a/ios/PacketTunnelCore/Actor/State+Extensions.swift b/ios/PacketTunnelCore/Actor/State+Extensions.swift index 6e6d40bfb760..66583b13b4bd 100644 --- a/ios/PacketTunnelCore/Actor/State+Extensions.swift +++ b/ios/PacketTunnelCore/Actor/State+Extensions.swift @@ -37,50 +37,6 @@ extension State { } } - var packetTunnelStatus: PacketTunnelStatus { - var status = PacketTunnelStatus() - - switch self { - case let .connecting(connState), - let .connected(connState), - let .reconnecting(connState), - let .disconnecting(connState): - switch connState.networkReachability { - case .reachable: - status.isNetworkReachable = true - case .unreachable: - status.isNetworkReachable = false - case .undetermined: - // TODO: fix me - status.isNetworkReachable = true - } - - status.numberOfFailedAttempts = connState.connectionAttemptCount - status.tunnelRelay = connState.selectedRelay.packetTunnelRelay - - case .disconnected, .initial: - break - - case let .error(blockedState): - status.blockedStateReason = blockedState.reason - } - - return status - } - - public var relayConstraints: RelayConstraints? { - switch self { - case let .connecting(connState), let .connected(connState), let .reconnecting(connState): - return connState.relayConstraints - - case let .error(blockedState): - return blockedState.relayConstraints - - case .initial, .disconnecting, .disconnected: - return nil - } - } - // MARK: - Logging func logFormat() -> String { diff --git a/ios/PacketTunnelCore/Actor/State.swift b/ios/PacketTunnelCore/Actor/State.swift index eba9f1baa832..943cb0317b12 100644 --- a/ios/PacketTunnelCore/Actor/State.swift +++ b/ios/PacketTunnelCore/Actor/State.swift @@ -54,7 +54,7 @@ import class WireGuardKitTypes.PrivateKey `.connecting`, `.reconnecting`, `.error` can be interrupted if the tunnel is requested to stop, which should segue actor towards `.disconnected` state. */ -public enum State { +enum State { /// Initial state at the time when actor is initialized but before the first connection attempt. case initial @@ -83,7 +83,7 @@ public enum State { } /// Policy describing what WG key to use for tunnel communication. -public enum KeyPolicy { +enum KeyPolicy { /// Use current key stored in device data. case useCurrent @@ -92,12 +92,12 @@ public enum KeyPolicy { } /// Enum describing network availability. -public enum NetworkReachability: Equatable { +public enum NetworkReachability: Equatable, Codable { case undetermined, reachable, unreachable } /// Data associated with states that hold connection data. -public struct ConnectionState { +struct ConnectionState { /// Current selected relay. public var selectedRelay: SelectedRelay @@ -130,7 +130,7 @@ public struct ConnectionState { } /// Data associated with error state. -public struct BlockedState { +struct BlockedState { /// Reason why block state was entered. public var reason: BlockedStateReason @@ -195,12 +195,12 @@ public enum BlockedStateReason: String, Codable, Equatable { } /// Legal states that can precede error state. -public enum StatePriorToBlockedState { +enum StatePriorToBlockedState { case initial, connecting, connected, reconnecting } /// Target state the actor should transition into upon request to either start (connect) or reconnect. -public enum TargetStateForReconnect { +enum TargetStateForReconnect { case reconnecting, connecting } @@ -217,7 +217,7 @@ public enum NextRelay: Equatable, Codable { } /// Describes the reason for reconnection request. -public enum ReconnectReason { +enum ReconnectReason { /// Initiated by user. case userInitiated diff --git a/ios/PacketTunnelCore/IPC/AppMessageHandler.swift b/ios/PacketTunnelCore/IPC/AppMessageHandler.swift index d72e2bf05b0a..4ad557f7bad2 100644 --- a/ios/PacketTunnelCore/IPC/AppMessageHandler.swift +++ b/ios/PacketTunnelCore/IPC/AppMessageHandler.swift @@ -47,7 +47,7 @@ public struct AppMessageHandler { return nil case .getTunnelStatus: - return await encodeReply(packetTunnelActor.state.packetTunnelStatus) + return await encodeReply(packetTunnelActor.observedState.packetTunnelStatus) case .privateKeyRotation: packetTunnelActor.notifyKeyRotation(date: Date()) diff --git a/ios/PacketTunnelCoreTests/AppMessageHandlerTests.swift b/ios/PacketTunnelCoreTests/AppMessageHandlerTests.swift index bea5a83e8b02..d11dd478023c 100644 --- a/ios/PacketTunnelCoreTests/AppMessageHandlerTests.swift +++ b/ios/PacketTunnelCoreTests/AppMessageHandlerTests.swift @@ -17,7 +17,6 @@ final class AppMessageHandlerTests: XCTestCase { func testHandleAppMessageForSendURLRequest() async throws { let sendRequestExpectation = expectation(description: "Expect sending request") - let actor = PacketTunnelActorStub() let urlRequestProxy = URLRequestProxyStub(sendRequestExpectation: sendRequestExpectation) let appMessageHandler = createAppMessageHandler(urlRequestProxy: urlRequestProxy) @@ -37,7 +36,6 @@ final class AppMessageHandlerTests: XCTestCase { func testHandleAppMessageForCancelURLRequest() async throws { let cancelRequestExpectation = expectation(description: "Expect cancelling request") - let actor = PacketTunnelActorStub() let urlRequestProxy = URLRequestProxyStub(cancelRequestExpectation: cancelRequestExpectation) let appMessageHandler = createAppMessageHandler(urlRequestProxy: urlRequestProxy) diff --git a/ios/PacketTunnelCoreTests/Mocks/PacketTunnelActorStub.swift b/ios/PacketTunnelCoreTests/Mocks/PacketTunnelActorStub.swift index 80c22971df6a..9dbc8f18fc51 100644 --- a/ios/PacketTunnelCoreTests/Mocks/PacketTunnelActorStub.swift +++ b/ios/PacketTunnelCoreTests/Mocks/PacketTunnelActorStub.swift @@ -11,12 +11,12 @@ import PacketTunnelCore import XCTest struct PacketTunnelActorStub: PacketTunnelActorProtocol { - let innerState: State = .disconnected + let innerState: ObservedState = .disconnected var stateExpectation: XCTestExpectation? var reconnectExpectation: XCTestExpectation? var keyRotationExpectation: XCTestExpectation? - var state: State { + var observedState: ObservedState { get async { stateExpectation?.fulfill() return innerState diff --git a/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift b/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift index 3bdf0b062f7f..e17f48c3302c 100644 --- a/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift +++ b/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift @@ -40,7 +40,7 @@ final class PacketTunnelActorTests: XCTestCase { let allExpectations = [initialStateExpectation, connectingExpectation, connectedStateExpectation] - stateSink = await actor.$state + stateSink = await actor.$observedState .receive(on: DispatchQueue.main) .sink { newState in switch newState { @@ -71,7 +71,7 @@ final class PacketTunnelActorTests: XCTestCase { let allExpectations = [initialStateExpectation, connectingExpectation, connectedStateExpectation] - stateSink = await actor.$state + stateSink = await actor.$observedState .receive(on: DispatchQueue.main) .sink { newState in switch newState { @@ -102,7 +102,7 @@ final class PacketTunnelActorTests: XCTestCase { let connectingStateExpectation = expectation(description: "Expect connecting state") connectingStateExpectation.expectedFulfillmentCount = 5 var nextAttemptCount: UInt = 0 - stateSink = await actor.$state + stateSink = await actor.$observedState .receive(on: DispatchQueue.main) .sink { newState in switch newState { @@ -136,7 +136,7 @@ final class PacketTunnelActorTests: XCTestCase { let reconnectingStateExpectation = expectation(description: "Expect reconnecting state") reconnectingStateExpectation.expectedFulfillmentCount = 5 var nextAttemptCount: UInt = 0 - stateSink = await actor.$state + stateSink = await actor.$observedState .receive(on: DispatchQueue.main) .sink { newState in switch newState { @@ -214,7 +214,7 @@ final class PacketTunnelActorTests: XCTestCase { let actor = PacketTunnelActor.mock(blockedStateErrorMapper: blockedStateMapper, settingsReader: settingsReader) - stateSink = await actor.$state + stateSink = await actor.$observedState .receive(on: DispatchQueue.main) .sink { newState in switch newState { @@ -241,7 +241,7 @@ final class PacketTunnelActorTests: XCTestCase { let disconnectedStateExpectation = expectation(description: "Expect disconnected state") let connectedStateExpectation = expectation(description: "Expect connected state") - let expression: (State) -> Bool = { if case .connected = $0 { true } else { false } } + let expression: (ObservedState) -> Bool = { if case .connected = $0 { true } else { false } } await expect(expression, on: actor) { connectedStateExpectation.fulfill() @@ -284,7 +284,7 @@ final class PacketTunnelActorTests: XCTestCase { didStopObserverExpectation.expectedFulfillmentCount = 2 pathObserver.onStop = { didStopObserverExpectation.fulfill() } - let expression: (State) -> Bool = { if case .connected = $0 { true } else { false } } + let expression: (ObservedState) -> Bool = { if case .connected = $0 { true } else { false } } await expect(expression, on: actor) { connectedStateExpectation.fulfill() @@ -309,7 +309,7 @@ final class PacketTunnelActorTests: XCTestCase { let errorStateExpectation = expectation(description: "Should not enter error state") errorStateExpectation.isInverted = true - stateSink = await actor.$state + stateSink = await actor.$observedState .receive(on: DispatchQueue.main) .sink { newState in switch newState { @@ -337,7 +337,7 @@ final class PacketTunnelActorTests: XCTestCase { let reconnectingStateExpectation = expectation(description: "Expect initial state") reconnectingStateExpectation.isInverted = true - let expression: (State) -> Bool = { if case .reconnecting = $0 { true } else { false } } + let expression: (ObservedState) -> Bool = { if case .reconnecting = $0 { true } else { false } } await expect(expression, on: actor) { reconnectingStateExpectation.fulfill() @@ -365,7 +365,7 @@ final class PacketTunnelActorTests: XCTestCase { let reconnectingStateExpectation = expectation(description: "Expect initial state") reconnectingStateExpectation.isInverted = true - let expression: (State) -> Bool = { if case .reconnecting = $0 { true } else { false } } + let expression: (ObservedState) -> Bool = { if case .reconnecting = $0 { true } else { false } } await expect(expression, on: actor) { reconnectingStateExpectation.fulfill() } @@ -390,7 +390,7 @@ final class PacketTunnelActorTests: XCTestCase { let actor = PacketTunnelActor.mock(tunnelMonitor: tunnelMonitor) let connectedExpectation = expectation(description: "Expect connected state") - let expression: (State) -> Bool = { if case .connected = $0 { return true } else { return false } } + let expression: (ObservedState) -> Bool = { if case .connected = $0 { return true } else { return false } } await expect(expression, on: actor) { connectedExpectation.fulfill() } @@ -406,8 +406,8 @@ final class PacketTunnelActorTests: XCTestCase { } extension PacketTunnelActorTests { - func expect(_ state: State, on actor: PacketTunnelActor, _ action: @escaping () -> Void) async { - stateSink = await actor.$state.receive(on: DispatchQueue.main).sink { newState in + func expect(_ state: ObservedState, on actor: PacketTunnelActor, _ action: @escaping () -> Void) async { + stateSink = await actor.$observedState.receive(on: DispatchQueue.main).sink { newState in if state == newState { action() } @@ -415,11 +415,11 @@ extension PacketTunnelActorTests { } func expect( - _ expression: @escaping (State) -> Bool, + _ expression: @escaping (ObservedState) -> Bool, on actor: PacketTunnelActor, _ action: @escaping () -> Void ) async { - stateSink = await actor.$state.receive(on: DispatchQueue.main).sink { newState in + stateSink = await actor.$observedState.receive(on: DispatchQueue.main).sink { newState in if expression(newState) { action() } @@ -427,10 +427,4 @@ extension PacketTunnelActorTests { } } -extension State: Equatable { - public static func == (lhs: State, rhs: State) -> Bool { - lhs.name == rhs.name - } -} - // swiftlint:disable:this file_length