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