mirror of
https://github.com/passepartoutvpn/passepartout-apple.git
synced 2024-12-24 02:21:00 +00:00
aeec943c58
Store module preferences in the Profile.userInfo field for atomicity. Access and modification are dramatically simplified, and synchronization comes for free. On the other side, fix provider preferences synchronization by using viewContext for the CloudKit container. Fixes #992
172 lines
6.2 KiB
Swift
172 lines
6.2 KiB
Swift
//
|
|
// ExtendedTunnelTests.swift
|
|
// Passepartout
|
|
//
|
|
// Created by Davide De Rosa on 9/12/24.
|
|
// Copyright (c) 2024 Davide De Rosa. All rights reserved.
|
|
//
|
|
// https://github.com/passepartoutvpn
|
|
//
|
|
// This file is part of Passepartout.
|
|
//
|
|
// Passepartout is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Passepartout is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
|
|
import Combine
|
|
@testable import CommonLibrary
|
|
import Foundation
|
|
import PassepartoutKit
|
|
import XCTest
|
|
|
|
final class ExtendedTunnelTests: XCTestCase {
|
|
private var subscriptions: Set<AnyCancellable> = []
|
|
}
|
|
|
|
@MainActor
|
|
extension ExtendedTunnelTests {
|
|
func test_givenTunnel_whenDisconnectWithError_thenPublishesLastErrorCode() async throws {
|
|
let env = InMemoryEnvironment()
|
|
let tunnel = Tunnel(strategy: FakeTunnelStrategy(environment: env))
|
|
let sut = ExtendedTunnel(tunnel: tunnel, environment: env, interval: 0.1)
|
|
|
|
let module = try DNSModule.Builder().tryBuild()
|
|
let profile = try Profile.Builder(modules: [module], activatingModules: true).tryBuild()
|
|
try await sut.connect(with: profile)
|
|
env.setEnvironmentValue(.crypto, forKey: TunnelEnvironmentKeys.lastErrorCode)
|
|
|
|
let exp = expectation(description: "Last error code")
|
|
var didCall = false
|
|
sut
|
|
.$lastErrorCode
|
|
.sink {
|
|
if !didCall, $0 != nil {
|
|
didCall = true
|
|
exp.fulfill()
|
|
}
|
|
}
|
|
.store(in: &subscriptions)
|
|
|
|
try await tunnel.disconnect()
|
|
await fulfillment(of: [exp], timeout: CommonLibraryTests.timeout)
|
|
XCTAssertEqual(sut.lastErrorCode, .crypto)
|
|
}
|
|
|
|
func test_givenTunnel_whenConnect_thenPublishesDataCount() async throws {
|
|
let env = InMemoryEnvironment()
|
|
let tunnel = Tunnel(strategy: FakeTunnelStrategy(environment: env))
|
|
let sut = ExtendedTunnel(tunnel: tunnel, environment: env, interval: 0.1)
|
|
|
|
let module = try DNSModule.Builder().tryBuild()
|
|
let profile = try Profile.Builder(modules: [module], activatingModules: true).tryBuild()
|
|
try await sut.install(profile)
|
|
|
|
let dataCount = DataCount(500, 700)
|
|
env.setEnvironmentValue(dataCount, forKey: TunnelEnvironmentKeys.dataCount)
|
|
XCTAssertEqual(sut.dataCount, nil)
|
|
|
|
let exp = expectation(description: "Data count")
|
|
var didCall = false
|
|
sut
|
|
.$dataCount
|
|
.sink {
|
|
if !didCall, $0 != nil {
|
|
didCall = true
|
|
exp.fulfill()
|
|
}
|
|
}
|
|
.store(in: &subscriptions)
|
|
|
|
try await tunnel.install(profile, connect: true, title: \.name)
|
|
await fulfillment(of: [exp], timeout: CommonLibraryTests.timeout)
|
|
XCTAssertEqual(sut.dataCount, dataCount)
|
|
}
|
|
|
|
func test_givenTunnelAndProcessor_whenInstall_thenProcessesProfile() async throws {
|
|
let env = InMemoryEnvironment()
|
|
let tunnel = Tunnel(strategy: FakeTunnelStrategy(environment: env))
|
|
let processor = MockTunnelProcessor()
|
|
let sut = ExtendedTunnel(tunnel: tunnel, environment: env, processor: processor, interval: 0.1)
|
|
|
|
let module = try DNSModule.Builder().tryBuild()
|
|
let profile = try Profile.Builder(modules: [module], activatingModules: true).tryBuild()
|
|
try await sut.install(profile)
|
|
|
|
XCTAssertEqual(tunnel.currentProfile?.id, profile.id)
|
|
// XCTAssertEqual(processor.titleCount, 1) // unused by FakeTunnelStrategy
|
|
XCTAssertEqual(processor.willInstallCount, 1)
|
|
}
|
|
|
|
func test_givenTunnel_whenStatusChanges_thenConnectionStatusIsExpected() async throws {
|
|
let env = InMemoryEnvironment()
|
|
let tunnel = Tunnel(strategy: FakeTunnelStrategy(environment: env))
|
|
let processor = MockTunnelProcessor()
|
|
let sut = ExtendedTunnel(tunnel: tunnel, environment: env, processor: processor, interval: 0.1)
|
|
|
|
let module = try DNSModule.Builder().tryBuild()
|
|
let profile = try Profile.Builder(modules: [module], activatingModules: true).tryBuild()
|
|
try await sut.install(profile)
|
|
|
|
XCTAssertEqual(tunnel.currentProfile?.id, profile.id)
|
|
// XCTAssertEqual(processor.titleCount, 1) // unused by FakeTunnelStrategy
|
|
XCTAssertEqual(processor.willInstallCount, 1)
|
|
}
|
|
|
|
func test_givenTunnelStatus_thenConnectionStatusIsExpected() async throws {
|
|
let allTunnelStatuses: [TunnelStatus] = [
|
|
.inactive,
|
|
.activating,
|
|
.active,
|
|
.deactivating
|
|
]
|
|
let allConnectionStatuses: [ConnectionStatus] = [
|
|
.disconnected,
|
|
.connecting,
|
|
.connected,
|
|
.disconnecting
|
|
]
|
|
|
|
let env = InMemoryEnvironment()
|
|
let key = TunnelEnvironmentKeys.connectionStatus
|
|
|
|
// no connection status, tunnel status unaffected
|
|
allTunnelStatuses.forEach {
|
|
XCTAssertEqual($0.withEnvironment(env), $0)
|
|
}
|
|
|
|
// has connection status
|
|
|
|
// affected if .active
|
|
let tunnelActive: TunnelStatus = .active
|
|
env.setEnvironmentValue(ConnectionStatus.connected, forKey: key)
|
|
XCTAssertEqual(tunnelActive.withEnvironment(env), .active)
|
|
allConnectionStatuses
|
|
.filter {
|
|
$0 != .connected
|
|
}
|
|
.forEach {
|
|
env.setEnvironmentValue($0, forKey: key)
|
|
XCTAssertEqual(tunnelActive.withEnvironment(env), .activating)
|
|
}
|
|
|
|
// unaffected otherwise
|
|
allTunnelStatuses
|
|
.filter {
|
|
$0 != .active
|
|
}
|
|
.forEach {
|
|
XCTAssertEqual($0.withEnvironment(env), $0)
|
|
}
|
|
}
|
|
}
|