-
Notifications
You must be signed in to change notification settings - Fork 354
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8e1a445
commit d76fa40
Showing
11 changed files
with
568 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
ios/MullvadPostQuantumTests/MullvadPostQuantum+Stubs.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// | ||
// MullvadPostQuantum+Stubs.swift | ||
// MullvadPostQuantumTests | ||
// | ||
// Created by Marco Nikic on 2024-06-12. | ||
// Copyright © 2024 Mullvad VPN AB. All rights reserved. | ||
// | ||
|
||
@testable import MullvadPostQuantum | ||
@testable import MullvadTypes | ||
import NetworkExtension | ||
@testable import PacketTunnelCore | ||
@testable import WireGuardKitTypes | ||
|
||
// swiftlint:disable function_parameter_count | ||
class NWTCPConnectionStub: NWTCPConnection { | ||
var _isViable = false | ||
override var isViable: Bool { | ||
_isViable | ||
} | ||
|
||
func becomeViable() { | ||
willChangeValue(for: \.isViable) | ||
_isViable = true | ||
didChangeValue(for: \.isViable) | ||
} | ||
} | ||
|
||
class TunnelProviderStub: TunnelProvider { | ||
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: PostQuantumKeyNegotiation { | ||
var onCancelKeyNegotiation: (() -> Void)? | ||
|
||
required init() { | ||
onCancelKeyNegotiation = nil | ||
} | ||
|
||
init(onCancelKeyNegotiation: (() -> Void)? = nil) { | ||
self.onCancelKeyNegotiation = onCancelKeyNegotiation | ||
} | ||
|
||
func startNegotiation( | ||
gatewayIP: IPv4Address, | ||
devicePublicKey: WireGuardKitTypes.PublicKey, | ||
presharedKey: WireGuardKitTypes.PrivateKey, | ||
packetTunnel: PacketTunnelCore.TunnelProvider, | ||
tcpConnection: NWTCPConnection, | ||
postQuantumKeyExchangeTimeout: MullvadTypes.Duration | ||
) -> Bool { false } | ||
|
||
func cancelKeyNegotiation() { | ||
onCancelKeyNegotiation?() | ||
} | ||
} | ||
|
||
class SuccessfulNegotiatorStub: PostQuantumKeyNegotiation { | ||
var onCancelKeyNegotiation: (() -> Void)? | ||
required init() { | ||
onCancelKeyNegotiation = nil | ||
} | ||
|
||
init(onCancelKeyNegotiation: (() -> Void)? = nil) { | ||
self.onCancelKeyNegotiation = onCancelKeyNegotiation | ||
} | ||
|
||
func startNegotiation( | ||
gatewayIP: IPv4Address, | ||
devicePublicKey: WireGuardKitTypes.PublicKey, | ||
presharedKey: WireGuardKitTypes.PrivateKey, | ||
packetTunnel: PacketTunnelCore.TunnelProvider, | ||
tcpConnection: NWTCPConnection, | ||
postQuantumKeyExchangeTimeout: MullvadTypes.Duration | ||
) -> Bool { true } | ||
|
||
func cancelKeyNegotiation() { | ||
onCancelKeyNegotiation?() | ||
} | ||
} | ||
|
||
// swiftlint:enable function_parameter_count |
91 changes: 91 additions & 0 deletions
91
ios/MullvadPostQuantumTests/PostQuantumKeyExchangeActorTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// | ||
// PostQuantumKeyExchangeActorTests.swift | ||
// PostQuantumKeyExchangeActorTests | ||
// | ||
// Created by Marco Nikic on 2024-06-12. | ||
// Copyright © 2024 Mullvad VPN AB. All rights reserved. | ||
// | ||
|
||
@testable import MullvadPostQuantum | ||
@testable import MullvadTypes | ||
import NetworkExtension | ||
@testable import PacketTunnelCore | ||
@testable import WireGuardKitTypes | ||
import XCTest | ||
|
||
class MullvadPostQuantumTests: XCTestCase { | ||
var tcpConnection: NWTCPConnectionStub! | ||
var tunnelProvider: TunnelProviderStub! | ||
|
||
override func setUpWithError() throws { | ||
tcpConnection = NWTCPConnectionStub() | ||
tunnelProvider = TunnelProviderStub(tcpConnection: tcpConnection) | ||
} | ||
|
||
func testKeyExchangeFailsWhenNegotiationCannotStart() { | ||
let negotiationFailure = expectation(description: "Negotiation failed") | ||
|
||
let keyExchangeActor = PostQuantumKeyExchangeActor( | ||
packetTunnel: tunnelProvider, | ||
onFailure: { | ||
negotiationFailure.fulfill() | ||
}, | ||
negotiationProvider: FailedNegotiatorStub.self | ||
) | ||
|
||
let privateKey = PrivateKey() | ||
keyExchangeActor.startNegotiation(with: privateKey) | ||
tcpConnection.becomeViable() | ||
|
||
wait(for: [negotiationFailure]) | ||
} | ||
|
||
func testKeyExchangeFailsWhenTCPConnectionIsNotReadyInTime() { | ||
let negotiationFailure = expectation(description: "Negotiation failed") | ||
|
||
// Setup the actor to wait only 10 milliseconds before declaring the TCP connection is not ready in time. | ||
let keyExchangeActor = PostQuantumKeyExchangeActor( | ||
packetTunnel: tunnelProvider, | ||
onFailure: { | ||
negotiationFailure.fulfill() | ||
}, | ||
negotiationProvider: FailedNegotiatorStub.self, | ||
keyExchangeRetriesIterator: AnyIterator { .milliseconds(10) } | ||
) | ||
|
||
let privateKey = PrivateKey() | ||
keyExchangeActor.startNegotiation(with: privateKey) | ||
|
||
wait(for: [negotiationFailure]) | ||
} | ||
|
||
func testResetEndsTheCurrentNegotiation() throws { | ||
let unexpectedNegotiationFailure = expectation(description: "Unexpected negotiation failure") | ||
unexpectedNegotiationFailure.isInverted = true | ||
|
||
let keyExchangeActor = PostQuantumKeyExchangeActor( | ||
packetTunnel: tunnelProvider, | ||
onFailure: { | ||
unexpectedNegotiationFailure.fulfill() | ||
}, | ||
negotiationProvider: SuccessfulNegotiatorStub.self | ||
) | ||
|
||
let privateKey = PrivateKey() | ||
keyExchangeActor.startNegotiation(with: privateKey) | ||
|
||
let negotiationProvider = try XCTUnwrap( | ||
keyExchangeActor.negotiation? | ||
.negotiator as? SuccessfulNegotiatorStub | ||
) | ||
|
||
let negotationCancelledExpectation = expectation(description: "Negotiation cancelled") | ||
negotiationProvider.onCancelKeyNegotiation = { | ||
negotationCancelledExpectation.fulfill() | ||
} | ||
|
||
keyExchangeActor.reset() | ||
|
||
wait(for: [negotationCancelledExpectation, unexpectedNegotiationFailure], timeout: 0.5) | ||
} | ||
} |
Oops, something went wrong.