Minor re-factoring for delegate and tests
This commit is contained in:
parent
5a2160ef16
commit
eb402cfb33
|
@ -6,7 +6,7 @@
|
|||
// Copyright © 2018 CocoaPods. All rights reserved.
|
||||
//
|
||||
|
||||
import ProxyResolver
|
||||
@testable import ProxyResolver
|
||||
|
||||
typealias ProxyConfigDict = [CFString: AnyObject]
|
||||
|
||||
|
@ -27,12 +27,7 @@ class MockProxyConfigProvider: ProxyConfigProvider {
|
|||
class MockProxyUrlFetcher: ProxyScriptFether {
|
||||
|
||||
func fetch(request: URLRequest, completion: @escaping (String?, Error?) -> Void) {
|
||||
let contents = """
|
||||
function FindProxyForURL(url, host) {
|
||||
return "PROXY \(TestConfigs.autoConfig.host):\(TestConfigs.autoConfig.port)";
|
||||
}
|
||||
""".trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
completion(contents, nil)
|
||||
completion(TestConfigs.autoConfig.scriptContents, nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -53,17 +48,15 @@ enum TestConfigs {
|
|||
static let scriptUrl = "https://autoconf.server.com"
|
||||
static let scriptContents = """
|
||||
function FindProxyForURL(url, host) {
|
||||
return "PROXY \(autoConfig.host):\(autoConfig.port)";
|
||||
return "PROXY \(autoConfig.httpProxy.host):\(autoConfig.httpProxy.port)";
|
||||
}
|
||||
"""
|
||||
static let host = "auto-http.proxy.com"
|
||||
static let port = 8000
|
||||
|
||||
static let httpProxy = Proxy(type: .http, host: "auto-http.proxy.com", port: 8000)
|
||||
static let httpsProxy = Proxy(type: .https, host: "auto-https.proxy.com", port: 8001)
|
||||
static let urlConfig = [
|
||||
[kCFProxyTypeKey: kCFProxyTypeAutoConfigurationURL,
|
||||
kCFProxyAutoConfigurationURLKey: scriptUrl as AnyObject]
|
||||
]
|
||||
|
||||
static let scriptConfig = [
|
||||
[kCFProxyTypeKey: kCFProxyTypeAutoConfigurationJavaScript,
|
||||
kCFProxyAutoConfigurationJavaScriptKey: scriptContents as AnyObject]
|
||||
|
@ -71,37 +64,41 @@ enum TestConfigs {
|
|||
}
|
||||
|
||||
enum http {
|
||||
static let host = "http.proxy.com"
|
||||
static let port = 8080
|
||||
|
||||
static let proxy = Proxy(type: .http, host: "http.proxy.com", port: 8080)
|
||||
static let config = [
|
||||
[kCFProxyTypeKey: kCFProxyTypeHTTP,
|
||||
kCFProxyHostNameKey: host as AnyObject,
|
||||
kCFProxyPortNumberKey: port as AnyObject]
|
||||
kCFProxyHostNameKey: proxy.host as AnyObject,
|
||||
kCFProxyPortNumberKey: proxy.port as AnyObject]
|
||||
]
|
||||
}
|
||||
|
||||
enum https {
|
||||
static let host = "http.proxy.com"
|
||||
static let port = 8081
|
||||
|
||||
static let proxy = Proxy(type: .https, host: "https.proxy.com", port: 8081)
|
||||
static let config = [
|
||||
[kCFProxyTypeKey: kCFProxyTypeHTTPS,
|
||||
kCFProxyHostNameKey: host as AnyObject,
|
||||
kCFProxyPortNumberKey: port as AnyObject]
|
||||
kCFProxyHostNameKey: proxy.host as AnyObject,
|
||||
kCFProxyPortNumberKey: proxy.port as AnyObject]
|
||||
]
|
||||
}
|
||||
|
||||
enum socks {
|
||||
static let host = "socks.proxy.com"
|
||||
static let port = 8082
|
||||
|
||||
static let proxy = Proxy(type: .socks, host: "socks", port: 8082)
|
||||
static let config = [
|
||||
[kCFProxyTypeKey: kCFProxyTypeSOCKS,
|
||||
kCFProxyHostNameKey: host as AnyObject,
|
||||
kCFProxyPortNumberKey: port as AnyObject]
|
||||
kCFProxyHostNameKey: proxy.host as AnyObject,
|
||||
kCFProxyPortNumberKey: proxy.port as AnyObject]
|
||||
]
|
||||
}
|
||||
// swiftlint:enable type_name
|
||||
|
||||
}
|
||||
|
||||
extension ProxyResolutionResult {
|
||||
func isSameSuccessfull(as other: ProxyResolutionResult) -> Bool {
|
||||
switch (self, other) {
|
||||
case (.direct, .direct): return true
|
||||
case let (.proxy(lproxy), .proxy(rproxy)): return lproxy == rproxy
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,31 +14,21 @@ class TestDelegate: ProxyResolverDelegate {
|
|||
var didStopExpectation: XCTestExpectation?
|
||||
var didResolveExpectation: XCTestExpectation?
|
||||
|
||||
var resolveNext: ((Bool) -> Void)?
|
||||
var resolveUrl: URL?
|
||||
var resolveResult: ProxyResolutionResult?
|
||||
var stopUrl: URL?
|
||||
var stopError: Error?
|
||||
var resolveNextRoutine: ResolveNextRoutine?
|
||||
|
||||
func proxyResolver(_ proxyResolver: ProxyResolver, didFinish url: URL, with error: Error?) {
|
||||
stopUrl = url
|
||||
stopError = error
|
||||
didStopExpectation?.fulfill()
|
||||
}
|
||||
|
||||
func proxyResolver(_ proxyResolver: ProxyResolver, didResolve url: URL, with result: ProxyResolutionResult,
|
||||
shouldResolveNext: @escaping (Bool) -> Void) {
|
||||
func proxyResolver(_ proxyResolver: ProxyResolver, didResolve result: ProxyResolutionResult, for url: URL,
|
||||
resolveNext: ResolveNextRoutine?) {
|
||||
resolveUrl = url
|
||||
resolveResult = result
|
||||
resolveNext = shouldResolveNext
|
||||
resolveNextRoutine = resolveNext
|
||||
didResolveExpectation?.fulfill()
|
||||
}
|
||||
|
||||
func clearResults() {
|
||||
resolveUrl = nil
|
||||
resolveResult = nil
|
||||
stopUrl = nil
|
||||
stopError = nil
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -89,9 +79,9 @@ class DelegateTests: XCTestCase {
|
|||
default:
|
||||
break
|
||||
}
|
||||
XCTAssertNotNil(testDelegate.resolveNext)
|
||||
XCTAssertNotNil(testDelegate.resolveNextRoutine)
|
||||
|
||||
testDelegate.resolveNext!(true)
|
||||
testDelegate.resolveNextRoutine!()
|
||||
wait(for: [resolveExpectation], timeout: TestConfigs.timeout)
|
||||
XCTAssertNotNil(testDelegate.resolveUrl)
|
||||
XCTAssert(testDelegate.resolveUrl! == TestConfigs.httpUrl)
|
||||
|
@ -103,12 +93,6 @@ class DelegateTests: XCTestCase {
|
|||
default:
|
||||
break
|
||||
}
|
||||
|
||||
testDelegate.resolveNext!(true)
|
||||
wait(for: [stopExpectation], timeout: TestConfigs.timeout)
|
||||
XCTAssertNotNil(testDelegate.stopUrl)
|
||||
XCTAssert(testDelegate.stopUrl! == TestConfigs.httpUrl)
|
||||
XCTAssertNil(testDelegate.stopError)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,17 +23,11 @@ class Tests: XCTestCase {
|
|||
|
||||
func testNoProxyResolve() {
|
||||
let expectation = XCTestExpectation(description: "Completion called")
|
||||
let expectedResult = ProxyResolutionResult.direct
|
||||
testConfigProvider.setTestConfig(TestConfigs.noProxy.config)
|
||||
|
||||
proxy.resolve(for: TestConfigs.httpUrl) { result in
|
||||
switch result {
|
||||
case .direct:
|
||||
XCTAssert(true)
|
||||
case .proxy(let proxy):
|
||||
XCTAssert(false, "Incorrect proxy connection resolved: \(proxy)")
|
||||
case .error(let error):
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
XCTAssert(result.isSameSuccessfull(as: expectedResult))
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation], timeout: TestConfigs.timeout)
|
||||
|
@ -41,19 +35,11 @@ class Tests: XCTestCase {
|
|||
|
||||
func testAutoConfigurationUrlResolve() {
|
||||
let expectation = XCTestExpectation(description: "Completion called")
|
||||
let expectedResult = ProxyResolutionResult.proxy(TestConfigs.autoConfig.httpProxy)
|
||||
testConfigProvider.setTestConfig(TestConfigs.autoConfig.urlConfig)
|
||||
|
||||
proxy.resolve(for: TestConfigs.httpUrl) { result in
|
||||
switch result {
|
||||
case .direct:
|
||||
XCTAssert(false, "Incorrect direct connection resolved")
|
||||
case .proxy(let proxy):
|
||||
XCTAssert(proxy.type == .http)
|
||||
XCTAssert(proxy.host == TestConfigs.autoConfig.host)
|
||||
XCTAssert(proxy.port == TestConfigs.autoConfig.port)
|
||||
case .error(let error):
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
XCTAssert(result.isSameSuccessfull(as: expectedResult))
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation], timeout: TestConfigs.timeout)
|
||||
|
@ -61,19 +47,11 @@ class Tests: XCTestCase {
|
|||
|
||||
func testAutoConfigurationScriptResolve() {
|
||||
let expectation = XCTestExpectation(description: "Completion called")
|
||||
let expectedResult = ProxyResolutionResult.proxy(TestConfigs.autoConfig.httpProxy)
|
||||
testConfigProvider.setTestConfig(TestConfigs.autoConfig.scriptConfig)
|
||||
|
||||
proxy.resolve(for: TestConfigs.httpUrl) { result in
|
||||
switch result {
|
||||
case .direct:
|
||||
XCTAssert(false, "Incorrect direct connection resolved")
|
||||
case .proxy(let proxy):
|
||||
XCTAssert(proxy.type == .http)
|
||||
XCTAssert(proxy.host == TestConfigs.autoConfig.host)
|
||||
XCTAssert(proxy.port == TestConfigs.autoConfig.port)
|
||||
case .error(let error):
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
XCTAssert(result.isSameSuccessfull(as: expectedResult))
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation], timeout: TestConfigs.timeout)
|
||||
|
@ -81,19 +59,11 @@ class Tests: XCTestCase {
|
|||
|
||||
func testHttpResolve() {
|
||||
let expectation = XCTestExpectation(description: "Completion called")
|
||||
let expectedResult = ProxyResolutionResult.proxy(TestConfigs.http.proxy)
|
||||
testConfigProvider.setTestConfig(TestConfigs.http.config)
|
||||
|
||||
proxy.resolve(for: TestConfigs.httpUrl) { result in
|
||||
switch result {
|
||||
case .direct:
|
||||
XCTAssert(false, "Incorrect direct connection resolved")
|
||||
case .proxy(let proxy):
|
||||
XCTAssert(proxy.type == .http)
|
||||
XCTAssert(proxy.host == TestConfigs.http.host)
|
||||
XCTAssert(proxy.port == TestConfigs.http.port)
|
||||
case .error(let error):
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
XCTAssert(result.isSameSuccessfull(as: expectedResult))
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation], timeout: TestConfigs.timeout)
|
||||
|
@ -101,19 +71,11 @@ class Tests: XCTestCase {
|
|||
|
||||
func testHttpsResolve() {
|
||||
let expectation = XCTestExpectation(description: "Completion called")
|
||||
let expectedResult = ProxyResolutionResult.proxy(TestConfigs.https.proxy)
|
||||
testConfigProvider.setTestConfig(TestConfigs.https.config)
|
||||
|
||||
proxy.resolve(for: TestConfigs.httpUrl) { result in
|
||||
switch result {
|
||||
case .direct:
|
||||
XCTAssert(false, "Incorrect direct connection resolved")
|
||||
case .proxy(let proxy):
|
||||
XCTAssert(proxy.type == .https)
|
||||
XCTAssert(proxy.host == TestConfigs.https.host)
|
||||
XCTAssert(proxy.port == TestConfigs.https.port)
|
||||
case .error(let error):
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
XCTAssert(result.isSameSuccessfull(as: expectedResult))
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation], timeout: TestConfigs.timeout)
|
||||
|
@ -121,19 +83,11 @@ class Tests: XCTestCase {
|
|||
|
||||
func testSocksResolve() {
|
||||
let expectation = XCTestExpectation(description: "Completion called")
|
||||
let expectedResult = ProxyResolutionResult.proxy(TestConfigs.socks.proxy)
|
||||
testConfigProvider.setTestConfig(TestConfigs.socks.config)
|
||||
|
||||
proxy.resolve(for: TestConfigs.httpUrl) { result in
|
||||
switch result {
|
||||
case .direct:
|
||||
XCTAssert(false, "Incorrect direct connection resolved")
|
||||
case .proxy(let proxy):
|
||||
XCTAssert(proxy.type == .socks)
|
||||
XCTAssert(proxy.host == TestConfigs.socks.host)
|
||||
XCTAssert(proxy.port == TestConfigs.socks.port)
|
||||
case .error(let error):
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
XCTAssert(result.isSameSuccessfull(as: expectedResult))
|
||||
expectation.fulfill()
|
||||
}
|
||||
wait(for: [expectation], timeout: TestConfigs.timeout)
|
||||
|
|
|
@ -31,6 +31,13 @@ public struct Proxy {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Swift 4.2 should have it auto-generated
|
||||
extension Proxy: Equatable {
|
||||
public static func == (lhs: Proxy, rhs: Proxy) -> Bool {
|
||||
return lhs.type == rhs.type && lhs.host == rhs.host && lhs.port == rhs.port
|
||||
}
|
||||
}
|
||||
|
||||
public enum ProxyResolutionResult {
|
||||
case direct
|
||||
case proxy(Proxy)
|
||||
|
@ -74,10 +81,11 @@ public final class ProxyResolverConfig {
|
|||
|
||||
// MARK: - ProxyResolverDelegate protocol
|
||||
|
||||
public typealias ResolveNextRoutine = () -> Void
|
||||
|
||||
public protocol ProxyResolverDelegate: class {
|
||||
func proxyResolver(_ proxyResolver: ProxyResolver, didFinish url: URL, with error: Error?)
|
||||
func proxyResolver(_ proxyResolver: ProxyResolver, didResolve url: URL, with result: ProxyResolutionResult,
|
||||
shouldResolveNext: @escaping (Bool) -> Void)
|
||||
func proxyResolver(_ proxyResolver: ProxyResolver, didResolve result: ProxyResolutionResult, for url: URL,
|
||||
resolveNext: ResolveNextRoutine?)
|
||||
}
|
||||
|
||||
// MARK: - ProxyResolver class
|
||||
|
@ -129,23 +137,24 @@ public final class ProxyResolver {
|
|||
!proxiesConfig.isEmpty
|
||||
else {
|
||||
let error = ProxyResolutionError.unexpectedError(nil)
|
||||
self.delegate?.proxyResolver(self, didFinish: url, with: error)
|
||||
let result = ProxyResolutionResult.error(error)
|
||||
self.delegate?.proxyResolver(self,
|
||||
didResolve: result,
|
||||
for: url,
|
||||
resolveNext: nil)
|
||||
return
|
||||
}
|
||||
|
||||
var resolveCompletion: ((ProxyResolutionResult) -> Void)!
|
||||
let shouldResolveNextCallback: (Bool) -> Void = { shouldResolve in
|
||||
guard shouldResolve, !proxiesConfig.isEmpty else {
|
||||
self.delegate?.proxyResolver(self, didFinish: url, with: nil)
|
||||
return
|
||||
}
|
||||
let resolveNextRoutine: ResolveNextRoutine = {
|
||||
guard !proxiesConfig.isEmpty else { return }
|
||||
self.resolveProxy(from: proxiesConfig.removeFirst(), for: normalizedUrl, completion: resolveCompletion)
|
||||
}
|
||||
resolveCompletion = { result in
|
||||
self.delegate?.proxyResolver(self,
|
||||
didResolve: url,
|
||||
with: result,
|
||||
shouldResolveNext: shouldResolveNextCallback)
|
||||
didResolve: result,
|
||||
for: url,
|
||||
resolveNext: resolveNextRoutine)
|
||||
}
|
||||
resolveProxy(from: proxiesConfig.removeFirst(), for: normalizedUrl, completion: resolveCompletion)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue