diff options
| author | Bug Magnet <marco.nikic@mullvad.net> | 2023-11-16 12:04:47 +0100 |
|---|---|---|
| committer | Bug Magnet <marco.nikic@mullvad.net> | 2023-11-22 10:22:39 +0100 |
| commit | 8f611cce7f950c2e9aa599147ae9eac95eb79c48 (patch) | |
| tree | a521b356f7ea1ece14957c46a0a54198d3d127fe | |
| parent | 78c485d0b8de59c812637385536f4579ba3ea30d (diff) | |
| download | mullvadvpn-8f611cce7f950c2e9aa599147ae9eac95eb79c48.tar.xz mullvadvpn-8f611cce7f950c2e9aa599147ae9eac95eb79c48.zip | |
Fix flaky actor tests
| -rw-r--r-- | ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift b/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift index 51dbc48b41..65c0fbcf09 100644 --- a/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift +++ b/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift @@ -301,25 +301,28 @@ final class PacketTunnelActorTests: XCTestCase { await fulfillment(of: [disconnectedStateExpectation, didStopObserverExpectation], timeout: 1) } - // FIXME: Reconsider if this test should exist. As it stands currently, it - // relies the packet tunnel process processing app message calls and a - // `stopTunnel()` call in a particular, deterministic order, which makes it - // unreliable. In reality, we cannot guarantee the order between those - // calls, and it fails almost reliably on low core count VMs. - func setErrorStateGetsCancelledWhenStopping() async throws { + func testCannotEnterErrorStateWhenStopping() async throws { let actor = PacketTunnelActor.mock() let connectingStateExpectation = expectation(description: "Connecting state") let disconnectedStateExpectation = expectation(description: "Disconnected state") let errorStateExpectation = expectation(description: "Should not enter error state") errorStateExpectation.isInverted = true + /// Because of how commands are processed by the actor's `CommandChannel` + /// `start` and `stop` cannot be chained together, otherwise there is a risk that the `start` command + /// gets coalesced by the `stop` command, and leaves the actor in its `.initial` state. + /// Guarantee here that the actor reaches the `.connecting` state before moving on. + let expression: (ObservedState) -> Bool = { if case .connecting = $0 { true } else { false } } + await expect(expression, on: actor) { + connectingStateExpectation.fulfill() + } + actor.start(options: launchOptions) + await fulfillment(of: [connectingStateExpectation], timeout: 1) + stateSink = await actor.$observedState .receive(on: DispatchQueue.main) .sink { newState in switch newState { - case .connecting: - actor.setErrorState(reason: .readSettings) - connectingStateExpectation.fulfill() case .error: errorStateExpectation.fulfill() case .disconnected: @@ -329,10 +332,10 @@ final class PacketTunnelActorTests: XCTestCase { } } - actor.start(options: launchOptions) actor.stop() + actor.setErrorState(reason: .readSettings) - await fulfillment(of: [connectingStateExpectation, disconnectedStateExpectation], timeout: 1) + await fulfillment(of: [disconnectedStateExpectation], timeout: 1) await fulfillment(of: [errorStateExpectation], timeout: Duration.milliseconds(100).timeInterval) } |
