Minor re-factoring for delegate and tests

This commit is contained in:
Mikhail Churbanov 2018-06-15 22:11:24 +03:00
parent 5a2160ef16
commit eb402cfb33
4 changed files with 63 additions and 119 deletions

View File

@ -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
}
}
}

View File

@ -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)
}
}

View File

@ -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)

View File

@ -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)
}