mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-24 00:00:05 +08:00
Improve connection testing
This commit is contained in:
@@ -12,46 +12,124 @@ import NetworkExtension
|
|||||||
|
|
||||||
class OpenVPNAdapterTests: XCTestCase {
|
class OpenVPNAdapterTests: XCTestCase {
|
||||||
|
|
||||||
enum ExpectationsType {
|
private class CustomFlow: NSObject, OpenVPNAdapterPacketFlow {
|
||||||
case connection
|
|
||||||
|
func readPackets(completionHandler: @escaping ([Data], [NSNumber]) -> Void) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let customFlow = CustomFlow()
|
func writePackets(_ packets: [Data], withProtocols protocols: [NSNumber]) -> Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
var expectations = [ExpectationsType : XCTestExpectation]()
|
}
|
||||||
|
|
||||||
|
private class AdapterDelegate: NSObject, OpenVPNAdapterDelegate {
|
||||||
|
|
||||||
|
let settingsHandler: (NEPacketTunnelNetworkSettings?) -> Void
|
||||||
|
let errorHandler: (Error) -> Void
|
||||||
|
let eventHandler: (OpenVPNAdapterEvent) -> Void
|
||||||
|
|
||||||
|
init(
|
||||||
|
settingsHandler: @escaping (NEPacketTunnelNetworkSettings?) -> Void,
|
||||||
|
errorHandler: @escaping (Error) -> Void,
|
||||||
|
eventHandler: @escaping (OpenVPNAdapterEvent) -> Void
|
||||||
|
) {
|
||||||
|
self.settingsHandler = settingsHandler
|
||||||
|
self.errorHandler = errorHandler
|
||||||
|
self.eventHandler = eventHandler
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func openVPNAdapter(
|
||||||
|
_ openVPNAdapter: OpenVPNAdapter,
|
||||||
|
configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?,
|
||||||
|
completionHandler: @escaping (Error?) -> Void
|
||||||
|
) {
|
||||||
|
settingsHandler(networkSettings)
|
||||||
|
completionHandler(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleError error: Error) {
|
||||||
|
errorHandler(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func openVPNAdapter(
|
||||||
|
_ openVPNAdapter: OpenVPNAdapter, handleEvent event: OpenVPNAdapterEvent, message: String?
|
||||||
|
) {
|
||||||
|
eventHandler(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleLogMessage logMessage: String) {
|
||||||
|
print(logMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private let customFlow = CustomFlow()
|
||||||
|
|
||||||
override func setUp() {
|
override func setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
expectations.removeAll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tearDown() {
|
override func tearDown() {
|
||||||
super.tearDown()
|
super.tearDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test connection to the VPN server without cert and key
|
func testVPNConnection() {
|
||||||
func testConnectionCAOnly() {
|
|
||||||
guard let vpnConfiguration = VPNProfile.caOnly.configuration.data(using: .utf8) else { fatalError() }
|
|
||||||
|
|
||||||
let adapter = OpenVPNAdapter()
|
|
||||||
|
|
||||||
let configuration = OpenVPNConfiguration()
|
let configuration = OpenVPNConfiguration()
|
||||||
configuration.fileContent = vpnConfiguration
|
configuration.fileContent = VPNProfile.live.configuration.data(using: .utf8)
|
||||||
configuration.settings = VPNProfile.caOnly.settings
|
|
||||||
configuration.disableClientCert = true
|
|
||||||
|
|
||||||
let result: OpenVPNProperties
|
var settings = VPNProfile.live.settings ?? [:]
|
||||||
|
|
||||||
|
if let key = VPNProfile.live.key, let cert = VPNProfile.live.cert {
|
||||||
|
settings["cert"] = cert.replacingOccurrences(of: "\n", with: "\\n")
|
||||||
|
settings["key"] = key.replacingOccurrences(of: "\n", with: "\\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration.settings = settings
|
||||||
|
|
||||||
|
let preEvaluation: OpenVPNConfigurationEvaluation
|
||||||
do {
|
do {
|
||||||
result = try adapter.apply(configuration: configuration)
|
preEvaluation = try OpenVPNAdapter.evaluate(configuration: configuration)
|
||||||
} catch {
|
} catch {
|
||||||
XCTFail("Failed to configure OpenVPN adapted due to error: \(error)")
|
XCTFail("Evaluation failed due to error: \(error)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard !preEvaluation.externalPki else {
|
||||||
|
XCTFail("Currently profile cannot be External PKI as it is not imlemented yet.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if preEvaluation.isPrivateKeyPasswordRequired {
|
||||||
|
guard let keyPassword = VPNProfile.live.keyPassword else {
|
||||||
|
XCTFail("Private key password required.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration.privateKeyPassword = keyPassword
|
||||||
|
}
|
||||||
|
|
||||||
|
let adapter = OpenVPNAdapter()
|
||||||
|
|
||||||
|
let finalEvaluation: OpenVPNConfigurationEvaluation
|
||||||
|
do {
|
||||||
|
finalEvaluation = try adapter.apply(configuration: configuration)
|
||||||
|
} catch {
|
||||||
|
XCTFail("Failed to apply OpenVPN configuration due to error: \(error)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !finalEvaluation.autologin {
|
||||||
|
guard let username = VPNProfile.live.username, let password = VPNProfile.live.password else {
|
||||||
|
XCTFail("If unable to autologin, username and password must be provided.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !result.autologin {
|
|
||||||
let credentials = OpenVPNCredentials()
|
let credentials = OpenVPNCredentials()
|
||||||
credentials.username = VPNProfile.caOnly.username
|
credentials.username = username
|
||||||
credentials.password = VPNProfile.caOnly.password
|
credentials.password = password
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try adapter.provide(credentials: credentials)
|
try adapter.provide(credentials: credentials)
|
||||||
@@ -61,119 +139,28 @@ class OpenVPNAdapterTests: XCTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expectations[.connection] = expectation(description: "me.ss-abramchuk.openvpn-adapter.connection")
|
let connectionExpectation = XCTestExpectation(
|
||||||
|
description: "Establish connection using \(VPNProfile.live.profileName)"
|
||||||
|
)
|
||||||
|
|
||||||
adapter.delegate = self
|
let adapterDelegate = AdapterDelegate(
|
||||||
adapter.connect(using: customFlow)
|
settingsHandler: { (settings) in
|
||||||
|
|
||||||
waitForExpectations(timeout: 30.0) { (error) in
|
},
|
||||||
adapter.disconnect()
|
errorHandler: { (error) in
|
||||||
}
|
XCTFail("Failed to establish conection due to error: \(error)")
|
||||||
}
|
},
|
||||||
|
eventHandler: { (event) in
|
||||||
|
guard event == .connected else { return }
|
||||||
|
|
||||||
// Test connection to the VPN server with cert and key
|
|
||||||
func testConnectionCAWithCertAndKey() {
|
|
||||||
guard let vpnConfiguration = VPNProfile.caWithCertAndKey.configuration.data(using: .utf8) else { fatalError() }
|
|
||||||
|
|
||||||
let adapter = OpenVPNAdapter()
|
|
||||||
|
|
||||||
let configuration = OpenVPNConfiguration()
|
|
||||||
configuration.fileContent = vpnConfiguration
|
|
||||||
configuration.settings = VPNProfile.caWithCertAndKey.settings
|
|
||||||
|
|
||||||
let result: OpenVPNProperties
|
|
||||||
do {
|
|
||||||
result = try adapter.apply(configuration: configuration)
|
|
||||||
} catch {
|
|
||||||
XCTFail("Failed to configure OpenVPN adapted due to error: \(error)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !result.autologin {
|
|
||||||
let credentials = OpenVPNCredentials()
|
|
||||||
credentials.username = VPNProfile.caWithCertAndKey.username
|
|
||||||
credentials.password = VPNProfile.caWithCertAndKey.password
|
|
||||||
|
|
||||||
do {
|
|
||||||
try adapter.provide(credentials: credentials)
|
|
||||||
} catch {
|
|
||||||
XCTFail("Failed to provide credentials. \(error)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
expectations[.connection] = expectation(description: "me.ss-abramchuk.openvpn-adapter.connection")
|
|
||||||
|
|
||||||
adapter.delegate = self
|
|
||||||
adapter.connect(using: customFlow)
|
|
||||||
|
|
||||||
waitForExpectations(timeout: 30.0) { (error) in
|
|
||||||
adapter.disconnect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test connection to the VPN server without credentials
|
|
||||||
func testConnectionWithoutCredentials() {
|
|
||||||
guard let vpnConfiguration = VPNProfile.withoutCredentials.configuration.data(using: .utf8) else { fatalError() }
|
|
||||||
|
|
||||||
let adapter = OpenVPNAdapter()
|
|
||||||
|
|
||||||
let configuration = OpenVPNConfiguration()
|
|
||||||
configuration.fileContent = vpnConfiguration
|
|
||||||
configuration.settings = VPNProfile.withoutCredentials.settings
|
|
||||||
|
|
||||||
let result: OpenVPNProperties
|
|
||||||
do {
|
|
||||||
result = try adapter.apply(configuration: configuration)
|
|
||||||
} catch {
|
|
||||||
XCTFail("Failed to configure OpenVPN adapted due to error: \(error)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
XCTAssertTrue(result.autologin)
|
|
||||||
|
|
||||||
expectations[.connection] = expectation(description: "me.ss-abramchuk.openvpn-adapter.connection")
|
|
||||||
|
|
||||||
adapter.delegate = self
|
|
||||||
adapter.connect(using: customFlow)
|
|
||||||
|
|
||||||
waitForExpectations(timeout: 30.0) { (error) in
|
|
||||||
adapter.disconnect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
extension OpenVPNAdapterTests: OpenVPNAdapterDelegate {
|
|
||||||
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?, completionHandler: @escaping (Error?) -> Void) {
|
|
||||||
completionHandler(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleEvent event: OpenVPNAdapterEvent, message: String?) {
|
|
||||||
switch event {
|
|
||||||
case .connected:
|
|
||||||
guard let connectionExpectation = expectations[.connection] else { return }
|
|
||||||
connectionExpectation.fulfill()
|
connectionExpectation.fulfill()
|
||||||
|
adapter.disconnect()
|
||||||
case .disconnected:
|
|
||||||
break
|
|
||||||
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleError error: Error) {
|
adapter.delegate = adapterDelegate
|
||||||
if let connectionExpectation = expectations[.connection] {
|
adapter.connect(using: customFlow)
|
||||||
XCTFail("Failed to establish conection.")
|
|
||||||
connectionExpectation.fulfill()
|
|
||||||
}
|
|
||||||
|
|
||||||
dump(error)
|
wait(for: [connectionExpectation], timeout: 15.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleLogMessage logMessage: String) {
|
|
||||||
print(logMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user