summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBug Magnet <marco.nikic@mullvad.net>2025-05-16 16:20:55 +0200
committerBug Magnet <marco.nikic@mullvad.net>2025-05-27 14:53:21 +0200
commitbbf890b10bda837308c05a3de6ac67df5aa2e06e (patch)
tree3cac8d83c8c28c2532d3649a5a13d2e54e351cc4
parent6c9f7ec18da5bd26ce5880e5dc8f5c8b83d5f77f (diff)
downloadmullvadvpn-bbf890b10bda837308c05a3de6ac67df5aa2e06e.tar.xz
mullvadvpn-bbf890b10bda837308c05a3de6ac67df5aa2e06e.zip
Enable Swift 6 mode for the PacketTunnel and test Target
-rw-r--r--ios/MullvadRustRuntimeTests/EphemeralPeerExchangeActorTests.swift5
-rw-r--r--ios/MullvadRustRuntimeTests/MullvadPostQuantum+Stubs.swift28
-rw-r--r--ios/MullvadRustRuntimeTests/TCPConnection.swift2
-rw-r--r--ios/MullvadRustRuntimeTests/UDPConnection.swift2
-rw-r--r--ios/MullvadTypes/Promise.swift2
-rw-r--r--ios/MullvadVPN.xcodeproj/project.pbxproj56
-rw-r--r--ios/MullvadVPNTests/MullvadLogging/LogFileOutputStreamTests.swift2
-rw-r--r--ios/MullvadVPNTests/MullvadSettings/IPOverrideRepositoryStub.swift2
-rw-r--r--ios/MullvadVPNTests/MullvadSettings/MigrationManagerMultiProcessUpgradeTests.swift4
-rw-r--r--ios/MullvadVPNTests/MullvadSettings/MigrationManagerTests.swift2
-rw-r--r--ios/MullvadVPNTests/MullvadVPN/Classes/InputTextFormatterTests.swift5
-rw-r--r--ios/MullvadVPNTests/MullvadVPN/PacketTunnel/DeviceCheck/DeviceCheckOperationTests.swift50
-rw-r--r--ios/PacketTunnel/DeviceCheck/DeviceCheckOperation.swift6
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider/NEProviderStopReason+Debug.swift2
-rw-r--r--ios/PacketTunnelCore/Actor/PacketTunnelActor+Extensions.swift2
-rw-r--r--ios/PacketTunnelCore/Actor/PacketTunnelActorCommand.swift2
-rw-r--r--ios/PacketTunnelCore/Pinger/PingerProtocol.swift2
-rw-r--r--ios/PacketTunnelCore/Pinger/TunnelPinger.swift2
-rw-r--r--ios/PacketTunnelCore/TunnelMonitor/TunnelDeviceInfoProtocol.swift2
-rw-r--r--ios/PacketTunnelCore/TunnelMonitor/TunnelMonitor.swift3
-rw-r--r--ios/PacketTunnelCore/TunnelMonitor/TunnelMonitorTimings.swift2
-rw-r--r--ios/PacketTunnelCore/URLRequestProxy/ProxyURLRequest.swift2
-rw-r--r--ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift20
-rw-r--r--ios/PacketTunnelCoreTests/Mocks/EphemeralPeerExchangeActorStub.swift2
-rw-r--r--ios/PacketTunnelCoreTests/Mocks/PacketTunnelActor+Mocks.swift4
-rw-r--r--ios/PacketTunnelCoreTests/Mocks/PingerMock.swift2
-rw-r--r--ios/PacketTunnelCoreTests/Mocks/TunnelDeviceInfoStub.swift2
-rw-r--r--ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift16
-rw-r--r--ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift2
-rw-r--r--ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift12
-rw-r--r--ios/PacketTunnelCoreTests/TunnelMonitorTests.swift8
31 files changed, 106 insertions, 147 deletions
diff --git a/ios/MullvadRustRuntimeTests/EphemeralPeerExchangeActorTests.swift b/ios/MullvadRustRuntimeTests/EphemeralPeerExchangeActorTests.swift
index efc8c0fe0d..82e0ebdb48 100644
--- a/ios/MullvadRustRuntimeTests/EphemeralPeerExchangeActorTests.swift
+++ b/ios/MullvadRustRuntimeTests/EphemeralPeerExchangeActorTests.swift
@@ -15,12 +15,10 @@ import NetworkExtension
import XCTest
class EphemeralPeerExchangeActorTests: XCTestCase {
- var tcpConnection: NWTCPConnectionStub!
var tunnelProvider: TunnelProviderStub!
override func setUpWithError() throws {
- tcpConnection = NWTCPConnectionStub()
- tunnelProvider = TunnelProviderStub(tcpConnection: tcpConnection)
+ tunnelProvider = TunnelProviderStub()
}
func testKeyExchangeFailsWhenNegotiationCannotStart() {
@@ -37,7 +35,6 @@ class EphemeralPeerExchangeActorTests: XCTestCase {
let privateKey = PrivateKey()
keyExchangeActor.startNegotiation(with: privateKey, enablePostQuantum: true, enableDaita: false)
- tcpConnection.becomeViable()
wait(for: [negotiationFailure])
}
diff --git a/ios/MullvadRustRuntimeTests/MullvadPostQuantum+Stubs.swift b/ios/MullvadRustRuntimeTests/MullvadPostQuantum+Stubs.swift
index 59805230be..a62771003e 100644
--- a/ios/MullvadRustRuntimeTests/MullvadPostQuantum+Stubs.swift
+++ b/ios/MullvadRustRuntimeTests/MullvadPostQuantum+Stubs.swift
@@ -12,19 +12,6 @@ import NetworkExtension
@testable import PacketTunnelCore
@testable import WireGuardKitTypes
-class NWTCPConnectionStub: NWTCPConnection {
- var _isViable = false
- override var isViable: Bool {
- _isViable
- }
-
- func becomeViable() {
- willChangeValue(for: \.isViable)
- _isViable = true
- didChangeValue(for: \.isViable)
- }
-}
-
class TunnelProviderStub: TunnelProvider {
func tunnelHandle() throws -> Int32 {
0
@@ -38,21 +25,6 @@ class TunnelProviderStub: TunnelProvider {
send: { _, _, _, _ in return 0 }
)
}
-
- let tcpConnection: NWTCPConnectionStub
-
- init(tcpConnection: NWTCPConnectionStub) {
- self.tcpConnection = tcpConnection
- }
-
- func createTCPConnectionThroughTunnel(
- to remoteEndpoint: NWEndpoint,
- enableTLS: Bool,
- tlsParameters TLSParameters: NWTLSParameters?,
- delegate: Any?
- ) -> NWTCPConnection {
- tcpConnection
- }
}
class FailedNegotiatorStub: EphemeralPeerNegotiating {
diff --git a/ios/MullvadRustRuntimeTests/TCPConnection.swift b/ios/MullvadRustRuntimeTests/TCPConnection.swift
index cffce29e4e..c4c74ce76a 100644
--- a/ios/MullvadRustRuntimeTests/TCPConnection.swift
+++ b/ios/MullvadRustRuntimeTests/TCPConnection.swift
@@ -11,7 +11,7 @@ import Network
/// Minimal implementation of TCP connection capable of receiving data.
/// > Warning: Do not use this implementation in production code. See the warning in `start()`.
-class TCPConnection: Connection {
+class TCPConnection: Connection, @unchecked Sendable {
private let dispatchQueue = DispatchQueue(label: "TCPConnection")
private let nwConnection: NWConnection
diff --git a/ios/MullvadRustRuntimeTests/UDPConnection.swift b/ios/MullvadRustRuntimeTests/UDPConnection.swift
index 66ef178d96..c4b3becc1d 100644
--- a/ios/MullvadRustRuntimeTests/UDPConnection.swift
+++ b/ios/MullvadRustRuntimeTests/UDPConnection.swift
@@ -16,7 +16,7 @@ protocol Connection {
/// Minimal implementation of UDP connection capable of sending data.
/// > Warning: Do not use this implementation in production code. See the warning in `start()`.
-class UDPConnection: Connection {
+class UDPConnection: Connection, @unchecked Sendable {
private let dispatchQueue = DispatchQueue(label: "UDPConnection")
private let nwConnection: NWConnection
diff --git a/ios/MullvadTypes/Promise.swift b/ios/MullvadTypes/Promise.swift
index b5f5a58873..3bf66e7ae3 100644
--- a/ios/MullvadTypes/Promise.swift
+++ b/ios/MullvadTypes/Promise.swift
@@ -52,7 +52,7 @@ public final class Promise<Success, Failure: Error>: @unchecked Sendable {
// allows the waiter to wait to `receive()` from another operation
// asynchronously. It is important not to forget to call `send`, otherwise this
// operation will block indefinitely.
-public struct OneshotChannel {
+public struct OneshotChannel: Sendable {
private var continuation: AsyncStream<Void>.Continuation?
private var stream: AsyncStream<Void>
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj
index de1e60d6b1..eb7a32dcd8 100644
--- a/ios/MullvadVPN.xcodeproj/project.pbxproj
+++ b/ios/MullvadVPN.xcodeproj/project.pbxproj
@@ -7338,7 +7338,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -7358,7 +7358,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
@@ -7469,7 +7469,7 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -7509,7 +7509,7 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -7532,7 +7532,7 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -7553,7 +7553,7 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
@@ -7755,7 +7755,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = minimal;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
};
name = Debug;
};
@@ -7775,7 +7775,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "$(APPLICATION_IDENTIFIER).PacketTunnel";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_STRICT_CONCURRENCY = minimal;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
};
name = Release;
};
@@ -8230,7 +8230,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG MULLVAD_ENVIRONMENT_PRODUCTION $(inherited)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/MullvadVPNUITests/BridgingHeader.h";
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = MullvadVPN;
};
@@ -8262,7 +8262,7 @@
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/MullvadVPNUITests/BridgingHeader.h";
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = MullvadVPN;
};
@@ -8396,7 +8396,7 @@
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Packet Tunnel Development";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_STRICT_CONCURRENCY = minimal;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
};
name = Staging;
};
@@ -8415,7 +8415,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Staging;
@@ -8634,7 +8634,7 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -8657,7 +8657,7 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Staging;
@@ -8789,7 +8789,7 @@
SUPPORTS_MACCATALYST = NO;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG MULLVAD_ENVIRONMENT_STAGING";
SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/MullvadVPNUITests/BridgingHeader.h";
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = MullvadVPN;
};
@@ -8813,7 +8813,7 @@
SUPPORTS_MACCATALYST = NO;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = MULLVAD_ENVIRONMENT_PRODUCTION;
SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/MullvadVPNUITests/BridgingHeader.h";
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = MullvadVPN;
};
@@ -8864,7 +8864,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -8915,7 +8915,7 @@
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -8966,7 +8966,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -9016,7 +9016,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -9044,7 +9044,7 @@
SUPPORTS_MACCATALYST = NO;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -9069,7 +9069,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Staging;
@@ -9094,7 +9094,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
@@ -9119,7 +9119,7 @@
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = MockRelease;
@@ -9242,7 +9242,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Packet Tunnel Development";
SWIFT_STRICT_CONCURRENCY = minimal;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
};
name = MockRelease;
};
@@ -9261,7 +9261,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = MockRelease;
@@ -9480,7 +9480,7 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -9503,7 +9503,7 @@
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
+ SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = MockRelease;
diff --git a/ios/MullvadVPNTests/MullvadLogging/LogFileOutputStreamTests.swift b/ios/MullvadVPNTests/MullvadLogging/LogFileOutputStreamTests.swift
index 87f215dd33..0ff1ab8df8 100644
--- a/ios/MullvadVPNTests/MullvadLogging/LogFileOutputStreamTests.swift
+++ b/ios/MullvadVPNTests/MullvadLogging/LogFileOutputStreamTests.swift
@@ -6,7 +6,7 @@
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
-import Foundation
+@preconcurrency import Foundation
@testable import MullvadLogging
import Testing
diff --git a/ios/MullvadVPNTests/MullvadSettings/IPOverrideRepositoryStub.swift b/ios/MullvadVPNTests/MullvadSettings/IPOverrideRepositoryStub.swift
index 6bd16f5432..36d60bf4f7 100644
--- a/ios/MullvadVPNTests/MullvadSettings/IPOverrideRepositoryStub.swift
+++ b/ios/MullvadVPNTests/MullvadSettings/IPOverrideRepositoryStub.swift
@@ -6,7 +6,7 @@
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
-import Combine
+@preconcurrency import Combine
import MullvadSettings
struct IPOverrideRepositoryStub: IPOverrideRepositoryProtocol {
diff --git a/ios/MullvadVPNTests/MullvadSettings/MigrationManagerMultiProcessUpgradeTests.swift b/ios/MullvadVPNTests/MullvadSettings/MigrationManagerMultiProcessUpgradeTests.swift
index 6e619256c5..d268171d99 100644
--- a/ios/MullvadVPNTests/MullvadSettings/MigrationManagerMultiProcessUpgradeTests.swift
+++ b/ios/MullvadVPNTests/MullvadSettings/MigrationManagerMultiProcessUpgradeTests.swift
@@ -26,8 +26,8 @@ extension MigrationManagerTests {
let backgroundMigrationExpectation = expectation(description: "Migration from packet tunnel")
let foregroundMigrationExpectation = expectation(description: "Migration from host")
- var migrationHappenedInPacketTunnel = false
- var migrationHappenedInHost = false
+ nonisolated(unsafe) var migrationHappenedInPacketTunnel = false
+ nonisolated(unsafe) var migrationHappenedInHost = false
packetTunnelProcess.async { [unowned self] in
manager.migrateSettings(store: MigrationManagerTests.store) { backgroundMigrationResult in
diff --git a/ios/MullvadVPNTests/MullvadSettings/MigrationManagerTests.swift b/ios/MullvadVPNTests/MullvadSettings/MigrationManagerTests.swift
index f62ca74403..ab93a2d37d 100644
--- a/ios/MullvadVPNTests/MullvadSettings/MigrationManagerTests.swift
+++ b/ios/MullvadVPNTests/MullvadSettings/MigrationManagerTests.swift
@@ -12,7 +12,7 @@
@testable import MullvadTypes
import XCTest
-final class MigrationManagerTests: XCTestCase {
+final class MigrationManagerTests: XCTestCase, @unchecked Sendable {
static let store = InMemorySettingsStore<SettingNotFound>()
var manager: MigrationManager!
diff --git a/ios/MullvadVPNTests/MullvadVPN/Classes/InputTextFormatterTests.swift b/ios/MullvadVPNTests/MullvadVPN/Classes/InputTextFormatterTests.swift
index def507f6a7..fb77a6f5e9 100644
--- a/ios/MullvadVPNTests/MullvadVPN/Classes/InputTextFormatterTests.swift
+++ b/ios/MullvadVPNTests/MullvadVPN/Classes/InputTextFormatterTests.swift
@@ -8,6 +8,7 @@
import XCTest
+@MainActor
class InputTextFormatterTests: XCTestCase {
private let accountNumber = "12345678"
private var inputTextFormatter: InputTextFormatter!
@@ -19,14 +20,14 @@ class InputTextFormatterTests: XCTestCase {
maxGroups: 4
)
- override func setUp() {
+ override func setUp() async throws {
inputTextFormatter = InputTextFormatter(
string: accountNumber,
configuration: configuration
)
}
- override func tearDown() {
+ override func tearDown() async throws {
inputTextFormatter = nil
}
diff --git a/ios/MullvadVPNTests/MullvadVPN/PacketTunnel/DeviceCheck/DeviceCheckOperationTests.swift b/ios/MullvadVPNTests/MullvadVPN/PacketTunnel/DeviceCheck/DeviceCheckOperationTests.swift
index fecc0f384b..8a5f95cb15 100644
--- a/ios/MullvadVPNTests/MullvadVPN/PacketTunnel/DeviceCheck/DeviceCheckOperationTests.swift
+++ b/ios/MullvadVPNTests/MullvadVPN/PacketTunnel/DeviceCheck/DeviceCheckOperationTests.swift
@@ -12,14 +12,14 @@ import MullvadSettings
import MullvadTypes
import Operations
import PacketTunnelCore
-import WireGuardKitTypes
+@preconcurrency import WireGuardKitTypes
import XCTest
class DeviceCheckOperationTests: XCTestCase {
private let operationQueue = AsyncOperationQueue()
private let dispatchQueue = DispatchQueue(label: "TestQueue")
- func testShouldReportExpiredAccount() {
+ func testShouldReportExpiredAccount() async {
let expect = expectation(description: "Wait for operation to complete")
let currentKey = PrivateKey()
@@ -45,10 +45,10 @@ class DeviceCheckOperationTests: XCTestCase {
expect.fulfill()
}
- waitForExpectations(timeout: .UnitTest.timeout)
+ await fulfillment(of: [expect], timeout: .UnitTest.timeout)
}
- func testShouldNotRotateKeyForInvalidAccount() {
+ func testShouldNotRotateKeyForInvalidAccount() async {
let expect = expectation(description: "Wait for operation to complete")
let currentKey = PrivateKey()
@@ -76,10 +76,10 @@ class DeviceCheckOperationTests: XCTestCase {
expect.fulfill()
}
- waitForExpectations(timeout: .UnitTest.timeout)
+ await fulfillment(of: [expect], timeout: .UnitTest.timeout)
}
- func testShouldNotRotateKeyForRevokedDevice() {
+ func testShouldNotRotateKeyForRevokedDevice() async {
let expect = expectation(description: "Wait for operation to complete")
let currentKey = PrivateKey()
@@ -107,10 +107,10 @@ class DeviceCheckOperationTests: XCTestCase {
expect.fulfill()
}
- waitForExpectations(timeout: .UnitTest.timeout)
+ await fulfillment(of: [expect], timeout: .UnitTest.timeout)
}
- func testShouldRotateKeyOnMismatchImmediately() {
+ func testShouldRotateKeyOnMismatchImmediately() async {
let expect = expectation(description: "Wait for operation to complete")
let currentKey = PrivateKey()
@@ -136,10 +136,10 @@ class DeviceCheckOperationTests: XCTestCase {
expect.fulfill()
}
- waitForExpectations(timeout: .UnitTest.timeout)
+ await fulfillment(of: [expect], timeout: .UnitTest.timeout)
}
- func testShouldRespectCooldownWhenAttemptingToRotateImmediately() {
+ func testShouldRespectCooldownWhenAttemptingToRotateImmediately() async {
let expect = expectation(description: "Wait for operation to complete")
let currentKey = PrivateKey()
@@ -165,10 +165,10 @@ class DeviceCheckOperationTests: XCTestCase {
expect.fulfill()
}
- waitForExpectations(timeout: .UnitTest.timeout)
+ await fulfillment(of: [expect], timeout: .UnitTest.timeout)
}
- func testShouldNotRotateDeviceKeyWhenServerKeyIsIdentical() {
+ func testShouldNotRotateDeviceKeyWhenServerKeyIsIdentical() async {
let expect = expectation(description: "Wait for operation to complete")
let currentKey = PrivateKey()
@@ -188,10 +188,10 @@ class DeviceCheckOperationTests: XCTestCase {
expect.fulfill()
}
- waitForExpectations(timeout: .UnitTest.timeout)
+ await fulfillment(of: [expect], timeout: .UnitTest.timeout)
}
- func testShouldNotRotateKeyBeforeRetryIntervalPassed() {
+ func testShouldNotRotateKeyBeforeRetryIntervalPassed() async {
let expect = expectation(description: "Wait for operation to complete")
let currentKey = PrivateKey()
@@ -213,10 +213,10 @@ class DeviceCheckOperationTests: XCTestCase {
expect.fulfill()
}
- waitForExpectations(timeout: .UnitTest.timeout)
+ await fulfillment(of: [expect], timeout: .UnitTest.timeout)
}
- func testShouldRotateKeyOnceInTwentyFourHours() {
+ func testShouldRotateKeyOnceInTwentyFourHours() async {
let expect = expectation(description: "Wait for operation to complete")
let currentKey = PrivateKey()
@@ -238,10 +238,10 @@ class DeviceCheckOperationTests: XCTestCase {
expect.fulfill()
}
- waitForExpectations(timeout: .UnitTest.timeout)
+ await fulfillment(of: [expect], timeout: .UnitTest.timeout)
}
- func testShouldReportFailedKeyRotationAttempt() {
+ func testShouldReportFailedKeyRotationAttempt() async {
let expect = expectation(description: "Wait for operation to complete")
let currentKey = PrivateKey()
@@ -268,10 +268,10 @@ class DeviceCheckOperationTests: XCTestCase {
expect.fulfill()
}
- waitForExpectations(timeout: .UnitTest.timeout)
+ await fulfillment(of: [expect], timeout: .UnitTest.timeout)
}
- func testShouldFailOnKeyRotationRace() {
+ func testShouldFailOnKeyRotationRace() async {
let expect = expectation(description: "Wait for operation to complete")
let currentKey = PrivateKey()
@@ -305,7 +305,7 @@ class DeviceCheckOperationTests: XCTestCase {
expect.fulfill()
}
- waitForExpectations(timeout: .UnitTest.timeout)
+ await fulfillment(of: [expect], timeout: .UnitTest.timeout)
}
private func startDeviceCheck(
@@ -327,7 +327,7 @@ class DeviceCheckOperationTests: XCTestCase {
}
/// Mock implementation of a remote service used by `DeviceCheckOperation` to reach the API.
-private class MockRemoteService: DeviceCheckRemoteServiceProtocol {
+private class MockRemoteService: DeviceCheckRemoteServiceProtocol, @unchecked Sendable {
typealias AccountDataHandler = (_ accountNumber: String) throws -> Account
typealias DeviceDataHandler = (_ accountNumber: String, _ deviceIdentifier: String) throws -> Device
typealias RotateDeviceKeyHandler = (
@@ -356,7 +356,7 @@ private class MockRemoteService: DeviceCheckRemoteServiceProtocol {
func getAccountData(
accountNumber: String,
- completion: @escaping (Result<Account, Error>) -> Void
+ completion: @escaping @Sendable (Result<Account, Error>) -> Void
) -> Cancellable {
DispatchQueue.main.async { [self] in
let result: Result<Account, Error> = Result {
@@ -374,7 +374,7 @@ private class MockRemoteService: DeviceCheckRemoteServiceProtocol {
func getDevice(
accountNumber: String,
identifier: String,
- completion: @escaping (Result<Device, Error>) -> Void
+ completion: @escaping @Sendable (Result<Device, Error>) -> Void
) -> Cancellable {
DispatchQueue.main.async { [self] in
let result: Result<Device, Error> = Result {
@@ -395,7 +395,7 @@ private class MockRemoteService: DeviceCheckRemoteServiceProtocol {
accountNumber: String,
identifier: String,
publicKey: PublicKey,
- completion: @escaping (Result<Device, Error>) -> Void
+ completion: @escaping @Sendable (Result<Device, Error>) -> Void
) -> Cancellable {
DispatchQueue.main.async { [self] in
let result: Result<Device, Error> = Result {
diff --git a/ios/PacketTunnel/DeviceCheck/DeviceCheckOperation.swift b/ios/PacketTunnel/DeviceCheck/DeviceCheckOperation.swift
index 926b94a9e3..ab88b22167 100644
--- a/ios/PacketTunnel/DeviceCheck/DeviceCheckOperation.swift
+++ b/ios/PacketTunnel/DeviceCheck/DeviceCheckOperation.swift
@@ -66,7 +66,7 @@ final class DeviceCheckOperation: ResultOperation<DeviceCheck>, @unchecked Senda
Begins the flow by fetching device state and then fetching account and device data. Calls `didReceiveData()` with
the received data when done.
*/
- private func startFlow(completion: @escaping (Result<DeviceCheck, Error>) -> Void) {
+ private func startFlow(completion: @escaping @Sendable (Result<DeviceCheck, Error>) -> Void) {
do {
guard case let .loggedIn(accountData, deviceData) = try deviceStateAccessor.read() else {
throw DeviceCheckError.invalidDeviceState
@@ -90,7 +90,7 @@ final class DeviceCheckOperation: ResultOperation<DeviceCheck>, @unchecked Senda
private func didReceiveData(
accountResult: Result<Account, Error>,
deviceResult: Result<Device, Error>,
- completion: @escaping (Result<DeviceCheck, Error>) -> Void
+ completion: @escaping @Sendable (Result<DeviceCheck, Error>) -> Void
) {
do {
let accountVerdict = try accountVerdict(from: accountResult)
@@ -158,7 +158,7 @@ final class DeviceCheckOperation: ResultOperation<DeviceCheck>, @unchecked Senda
then it rotate device key by marking the beginning of key rotation, updating device state and persisting before
proceeding to rotate the key.
*/
- private func rotateKeyIfNeeded(completion: @escaping (Result<KeyRotationStatus, Error>) -> Void) {
+ private func rotateKeyIfNeeded(completion: @escaping @Sendable (Result<KeyRotationStatus, Error>) -> Void) {
let deviceState: DeviceState
do {
deviceState = try deviceStateAccessor.read()
diff --git a/ios/PacketTunnel/PacketTunnelProvider/NEProviderStopReason+Debug.swift b/ios/PacketTunnel/PacketTunnelProvider/NEProviderStopReason+Debug.swift
index cb749f68a5..a86bebbd54 100644
--- a/ios/PacketTunnel/PacketTunnelProvider/NEProviderStopReason+Debug.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider/NEProviderStopReason+Debug.swift
@@ -46,6 +46,8 @@ extension NEProviderStopReason: CustomStringConvertible {
return "sleep"
case .appUpdate:
return "app update"
+ case .internalError:
+ return "internal error"
@unknown default:
return "unknown value (\(rawValue))"
}
diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActor+Extensions.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActor+Extensions.swift
index 7ae35c4685..5345287b73 100644
--- a/ios/PacketTunnelCore/Actor/PacketTunnelActor+Extensions.swift
+++ b/ios/PacketTunnelCore/Actor/PacketTunnelActor+Extensions.swift
@@ -6,7 +6,7 @@
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
-import Combine
+@preconcurrency import Combine
import Foundation
extension PacketTunnelActor {
diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActorCommand.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActorCommand.swift
index 9cf3833bb8..c467ca270d 100644
--- a/ios/PacketTunnelCore/Actor/PacketTunnelActorCommand.swift
+++ b/ios/PacketTunnelCore/Actor/PacketTunnelActorCommand.swift
@@ -7,7 +7,7 @@
//
import Foundation
-import MullvadTypes
+@preconcurrency import MullvadTypes
import Network
import WireGuardKitTypes
diff --git a/ios/PacketTunnelCore/Pinger/PingerProtocol.swift b/ios/PacketTunnelCore/Pinger/PingerProtocol.swift
index 1c06c634f9..0da7f7a3f0 100644
--- a/ios/PacketTunnelCore/Pinger/PingerProtocol.swift
+++ b/ios/PacketTunnelCore/Pinger/PingerProtocol.swift
@@ -29,7 +29,7 @@ public struct PingerSendResult {
}
/// A type capable of sending and receving ICMP traffic.
-public protocol PingerProtocol {
+public protocol PingerProtocol: Sendable {
var onReply: ((PingerReply) -> Void)? { get set }
func startPinging(destAddress: IPv4Address) throws
diff --git a/ios/PacketTunnelCore/Pinger/TunnelPinger.swift b/ios/PacketTunnelCore/Pinger/TunnelPinger.swift
index 10807e7362..20defd7a90 100644
--- a/ios/PacketTunnelCore/Pinger/TunnelPinger.swift
+++ b/ios/PacketTunnelCore/Pinger/TunnelPinger.swift
@@ -12,7 +12,7 @@ import Network
import PacketTunnelCore
import WireGuardKit
-public final class TunnelPinger: PingerProtocol {
+public final class TunnelPinger: PingerProtocol, @unchecked Sendable {
private var sequenceNumber: UInt16 = 0
private let stateLock = NSLock()
private let pingReceiveQueue: DispatchQueue
diff --git a/ios/PacketTunnelCore/TunnelMonitor/TunnelDeviceInfoProtocol.swift b/ios/PacketTunnelCore/TunnelMonitor/TunnelDeviceInfoProtocol.swift
index 664fd69ed9..d9a0a33250 100644
--- a/ios/PacketTunnelCore/TunnelMonitor/TunnelDeviceInfoProtocol.swift
+++ b/ios/PacketTunnelCore/TunnelMonitor/TunnelDeviceInfoProtocol.swift
@@ -9,7 +9,7 @@
import Foundation
/// A type that can provide statistics and basic information about tunnel device.
-public protocol TunnelDeviceInfoProtocol {
+public protocol TunnelDeviceInfoProtocol: Sendable {
/// Returns tunnel interface name (i.e utun0) if available.
var interfaceName: String? { get }
diff --git a/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitor.swift b/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitor.swift
index c1160d25f2..9d20efcc01 100644
--- a/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitor.swift
+++ b/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitor.swift
@@ -13,7 +13,7 @@ import Network
import NetworkExtension
/// Tunnel monitor.
-public final class TunnelMonitor: TunnelMonitorProtocol {
+public final class TunnelMonitor: TunnelMonitorProtocol, @unchecked Sendable {
private let tunnelDeviceInfo: TunnelDeviceInfoProtocol
private let nslock = NSLock()
@@ -22,7 +22,6 @@ public final class TunnelMonitor: TunnelMonitorProtocol {
private let timings: TunnelMonitorTimings
private var pinger: PingerProtocol
- private var isObservingDefaultPath = false
private var timer: DispatchSourceTimer?
private var state: TunnelMonitorState
diff --git a/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitorTimings.swift b/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitorTimings.swift
index 7e925ec932..ee1836bb22 100644
--- a/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitorTimings.swift
+++ b/ios/PacketTunnelCore/TunnelMonitor/TunnelMonitorTimings.swift
@@ -8,7 +8,7 @@
import MullvadTypes
-public struct TunnelMonitorTimings {
+public struct TunnelMonitorTimings: Sendable {
/// Interval for periodic heartbeat ping issued when traffic is flowing.
/// Should help to detect connectivity issues on networks that drop traffic in one of directions,
/// regardless if tx/rx counters are being updated.
diff --git a/ios/PacketTunnelCore/URLRequestProxy/ProxyURLRequest.swift b/ios/PacketTunnelCore/URLRequestProxy/ProxyURLRequest.swift
index e40f9d78e5..82e33e8c03 100644
--- a/ios/PacketTunnelCore/URLRequestProxy/ProxyURLRequest.swift
+++ b/ios/PacketTunnelCore/URLRequestProxy/ProxyURLRequest.swift
@@ -9,7 +9,7 @@
import Foundation
/// Struct describing serializable URLRequest data.
-public struct ProxyURLRequest: Codable {
+public struct ProxyURLRequest: Codable, Sendable {
public let id: UUID
public let url: URL
public let method: String?
diff --git a/ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift b/ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift
index 85737b4bc9..d340974131 100644
--- a/ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift
+++ b/ios/PacketTunnelCoreTests/EphemeralPeerExchangingPipelineTests.swift
@@ -89,10 +89,7 @@ final class EphemeralPeerExchangingPipelineTests: XCTestCase {
let connectionState = stubConnectionState(enableMultiHop: false, enablePostQuantum: true, enableDaita: false)
await postQuantumKeyExchangingPipeline.startNegotiation(connectionState, privateKey: PrivateKey())
- wait(
- for: [reconfigurationExpectation, negotiationSuccessful],
- timeout: .UnitTest.invertedTimeout
- )
+ await fulfillment(of: [reconfigurationExpectation, negotiationSuccessful], timeout: .UnitTest.invertedTimeout)
}
func testSingleHopDaitaPeerExchange() async throws {
@@ -123,10 +120,7 @@ final class EphemeralPeerExchangingPipelineTests: XCTestCase {
let connectionState = stubConnectionState(enableMultiHop: false, enablePostQuantum: false, enableDaita: true)
await postQuantumKeyExchangingPipeline.startNegotiation(connectionState, privateKey: PrivateKey())
- wait(
- for: [reconfigurationExpectation, negotiationSuccessful],
- timeout: .UnitTest.invertedTimeout
- )
+ await fulfillment(of: [reconfigurationExpectation, negotiationSuccessful], timeout: .UnitTest.invertedTimeout)
}
func testMultiHopPostQuantumKeyExchange() async throws {
@@ -158,10 +152,7 @@ final class EphemeralPeerExchangingPipelineTests: XCTestCase {
let connectionState = stubConnectionState(enableMultiHop: true, enablePostQuantum: true, enableDaita: false)
await postQuantumKeyExchangingPipeline.startNegotiation(connectionState, privateKey: PrivateKey())
- wait(
- for: [reconfigurationExpectation, negotiationSuccessful],
- timeout: .UnitTest.invertedTimeout
- )
+ await fulfillment(of: [reconfigurationExpectation, negotiationSuccessful], timeout: .UnitTest.invertedTimeout)
}
func testMultiHopDaitaExchange() async throws {
@@ -188,10 +179,7 @@ final class EphemeralPeerExchangingPipelineTests: XCTestCase {
let connectionState = stubConnectionState(enableMultiHop: true, enablePostQuantum: false, enableDaita: true)
await postQuantumKeyExchangingPipeline.startNegotiation(connectionState, privateKey: PrivateKey())
- wait(
- for: [reconfigurationExpectation, negotiationSuccessful],
- timeout: .UnitTest.invertedTimeout
- )
+ await fulfillment(of: [reconfigurationExpectation, negotiationSuccessful], timeout: .UnitTest.invertedTimeout)
}
func stubConnectionState(
diff --git a/ios/PacketTunnelCoreTests/Mocks/EphemeralPeerExchangeActorStub.swift b/ios/PacketTunnelCoreTests/Mocks/EphemeralPeerExchangeActorStub.swift
index 9766aac9ec..341e41eba6 100644
--- a/ios/PacketTunnelCoreTests/Mocks/EphemeralPeerExchangeActorStub.swift
+++ b/ios/PacketTunnelCoreTests/Mocks/EphemeralPeerExchangeActorStub.swift
@@ -12,7 +12,7 @@ import NetworkExtension
@testable import PacketTunnelCore
@testable import WireGuardKitTypes
-final class EphemeralPeerExchangeActorStub: EphemeralPeerExchangeActorProtocol {
+final class EphemeralPeerExchangeActorStub: EphemeralPeerExchangeActorProtocol, @unchecked Sendable {
typealias KeyNegotiationResult = Result<(PreSharedKey, PrivateKey), EphemeralPeerExchangeErrorStub>
var result: KeyNegotiationResult = .failure(.unknown)
diff --git a/ios/PacketTunnelCoreTests/Mocks/PacketTunnelActor+Mocks.swift b/ios/PacketTunnelCoreTests/Mocks/PacketTunnelActor+Mocks.swift
index bb8d94a806..135b2a3e1c 100644
--- a/ios/PacketTunnelCoreTests/Mocks/PacketTunnelActor+Mocks.swift
+++ b/ios/PacketTunnelCoreTests/Mocks/PacketTunnelActor+Mocks.swift
@@ -8,8 +8,8 @@
import Foundation
import MullvadMockData
-import MullvadREST
-import PacketTunnelCore
+@preconcurrency import MullvadREST
+@preconcurrency import PacketTunnelCore
extension PacketTunnelActorTimings {
static var timingsForTests: PacketTunnelActorTimings {
diff --git a/ios/PacketTunnelCoreTests/Mocks/PingerMock.swift b/ios/PacketTunnelCoreTests/Mocks/PingerMock.swift
index 9c468fd45d..bab560267e 100644
--- a/ios/PacketTunnelCoreTests/Mocks/PingerMock.swift
+++ b/ios/PacketTunnelCoreTests/Mocks/PingerMock.swift
@@ -12,7 +12,7 @@ import Network
@testable import PacketTunnelCore
/// Ping client mock that can be used to simulate network transmission errors and delays.
-class PingerMock: PingerProtocol {
+class PingerMock: PingerProtocol, @unchecked Sendable {
typealias OutcomeDecider = (IPv4Address, UInt16) -> Outcome
private let decideOutcome: OutcomeDecider
diff --git a/ios/PacketTunnelCoreTests/Mocks/TunnelDeviceInfoStub.swift b/ios/PacketTunnelCoreTests/Mocks/TunnelDeviceInfoStub.swift
index 40aaafee73..e6cde648ba 100644
--- a/ios/PacketTunnelCoreTests/Mocks/TunnelDeviceInfoStub.swift
+++ b/ios/PacketTunnelCoreTests/Mocks/TunnelDeviceInfoStub.swift
@@ -10,7 +10,7 @@ import Foundation
import PacketTunnelCore
/// Tunnel device stub that returns fixed interface name and feeds network stats from the type implementing `NetworkStatsProviding`
-struct TunnelDeviceInfoStub: TunnelDeviceInfoProtocol {
+struct TunnelDeviceInfoStub: TunnelDeviceInfoProtocol, @unchecked Sendable {
let networkStatsProviding: NetworkStatsProviding
var interfaceName: String? {
diff --git a/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift b/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift
index 4e77a6b617..7221e72a55 100644
--- a/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift
+++ b/ios/PacketTunnelCoreTests/MultiHopEphemeralPeerExchangerTests.swift
@@ -90,8 +90,8 @@ final class MultiHopEphemeralPeerExchangerTests: XCTestCase {
await multiHopExchanger.start()
- wait(
- for: [expectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
+ await fulfillment(
+ of: [expectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
timeout: .UnitTest.invertedTimeout
)
}
@@ -133,8 +133,8 @@ final class MultiHopEphemeralPeerExchangerTests: XCTestCase {
})
await multiHopPeerExchanger.start()
- wait(
- for: [unexpectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
+ await fulfillment(
+ of: [unexpectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
timeout: .UnitTest.invertedTimeout
)
}
@@ -171,8 +171,8 @@ final class MultiHopEphemeralPeerExchangerTests: XCTestCase {
})
await multiHopPeerExchanger.start()
- wait(
- for: [unexpectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
+ await fulfillment(
+ of: [unexpectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
timeout: .UnitTest.invertedTimeout
)
}
@@ -213,8 +213,8 @@ final class MultiHopEphemeralPeerExchangerTests: XCTestCase {
})
await multiHopPeerExchanger.start()
- wait(
- for: [unexpectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
+ await fulfillment(
+ of: [unexpectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
timeout: .UnitTest.invertedTimeout
)
}
diff --git a/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift b/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift
index 484e69ffe1..2c4e145b1c 100644
--- a/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift
+++ b/ios/PacketTunnelCoreTests/PacketTunnelActorTests.swift
@@ -6,7 +6,7 @@
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//
-import Combine
+@preconcurrency import Combine
@testable import MullvadMockData
@testable import MullvadREST
@testable import MullvadSettings
diff --git a/ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift b/ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift
index cba495a596..7707ffabf7 100644
--- a/ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift
+++ b/ios/PacketTunnelCoreTests/SingleHopEphemeralPeerExchangerTests.swift
@@ -68,8 +68,8 @@ final class SingleHopEphemeralPeerExchangerTests: XCTestCase {
await singleHopPostQuantumKeyExchanging.start()
- wait(
- for: [expectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
+ await fulfillment(
+ of: [expectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
timeout: .UnitTest.invertedTimeout
)
}
@@ -110,8 +110,8 @@ final class SingleHopEphemeralPeerExchangerTests: XCTestCase {
})
await singleHopPostQuantumKeyExchanging.start()
- wait(
- for: [unexpectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
+ await fulfillment(
+ of: [unexpectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
timeout: .UnitTest.invertedTimeout
)
}
@@ -147,8 +147,8 @@ final class SingleHopEphemeralPeerExchangerTests: XCTestCase {
})
await multiHopPeerExchanger.start()
- wait(
- for: [unexpectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
+ await fulfillment(
+ of: [unexpectedNegotiationFailure, reconfigurationExpectation, negotiationSuccessful],
timeout: .UnitTest.invertedTimeout
)
}
diff --git a/ios/PacketTunnelCoreTests/TunnelMonitorTests.swift b/ios/PacketTunnelCoreTests/TunnelMonitorTests.swift
index 5f15b7cf45..62d0fc057f 100644
--- a/ios/PacketTunnelCoreTests/TunnelMonitorTests.swift
+++ b/ios/PacketTunnelCoreTests/TunnelMonitorTests.swift
@@ -15,7 +15,7 @@ import XCTest
final class TunnelMonitorTests: XCTestCase {
let networkCounters = NetworkCounters()
- func testShouldDetermineConnectionEstablished() throws {
+ func testShouldDetermineConnectionEstablished() async throws {
let connectedExpectation = expectation(description: "Should report connected.")
let connectionLostExpectation = expectation(description: "Should not report connection loss")
connectionLostExpectation.isInverted = true
@@ -38,10 +38,10 @@ final class TunnelMonitorTests: XCTestCase {
tunnelMonitor.start(probeAddress: .loopback)
- waitForExpectations(timeout: .UnitTest.invertedTimeout)
+ await fulfillment(of: [connectedExpectation, connectionLostExpectation], timeout: .UnitTest.invertedTimeout)
}
- func testInitialConnectionTimings() {
+ func testInitialConnectionTimings() async throws {
// Setup pinger so that it never receives any replies.
let pinger = PingerMock(networkStatsReporting: networkCounters) { _, _ in .ignore }
@@ -108,7 +108,7 @@ final class TunnelMonitorTests: XCTestCase {
// Start monitoring.
tunnelMonitor.start(probeAddress: .loopback)
- waitForExpectations(timeout: TimeInterval(timeout) / 1000)
+ await fulfillment(of: [expectation], timeout: TimeInterval(timeout) / 1000)
}
}