diff --git a/SSHTests/SSHErrorTests.swift b/SSHTests/SSHErrorTests.swift index 9fad29c25..2193f4467 100644 --- a/SSHTests/SSHErrorTests.swift +++ b/SSHTests/SSHErrorTests.swift @@ -35,6 +35,17 @@ import Dispatch @testable import SSH +func __assertCompletionFailure(_ completion: Any?, withError error: SSHError, file: StaticString = #filePath, line: UInt = #line) { + guard + let c = completion as? Subscribers.Completion, + let err = c.error as? SSHError, + err == error + else { + XCTFail("Should completed with .faulure(\(error). Got: " + String(describing: completion), file: file, line: line) + return + } +} + class SSHErrorTests: XCTestCase { /** @@ -45,88 +56,60 @@ class SSHErrorTests: XCTestCase { - SSHError.notImplemented(_:) */ - var cancellableBag = Set() - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - /** SSHError.authError(:) is thrown when trying to use a method to authenticate on a host that's not allowed. In this case is trying to use `AuthNone()` as an authetnication method for a host that doesn't accept it. */ - func testAuthError() throws { + func testAuthError() { let config = SSHClientConfig( user: MockCredentials.wrongCredentials.user, port: MockCredentials.port, authMethods: [] ) - let expectation = self.expectation(description: "Buffer Written") - - SSHClient.dial(MockCredentials.wrongCredentials.host, with: config) - .sink(receiveCompletion: { completion in - switch completion { - case .finished: - XCTFail("Authentication should not have succeeded") - case .failure(let error as SSHError): - dump(error) - if error == .authError(msg: "") { - expectation.fulfill() - } else { - XCTFail("Unknown error") - } - case .failure(_): - XCTFail("It should present an error of type SSHError.authError(msg:)") + var completion: Any? = nil + + SSHClient + .dial(MockCredentials.wrongCredentials.host, with: config) + .sink( + test: self, + receiveCompletion: { + completion = $0 + }, + receiveValue: { _ in + XCTFail("Should not have received a connection") } - }, receiveValue: { _ in - XCTFail("Should not have received a connection") - }).store(in: &cancellableBag) + ) - waitForExpectations(timeout: 5, handler: nil) + __assertCompletionFailure(completion, withError: .authError(msg: "")) } - func testConnectionError() throws { - + func testConnectionError() { let config = SSHClientConfig( user: MockCredentials.wrongHost.user, port: MockCredentials.port, authMethods: [AuthPassword(with: MockCredentials.wrongHost.password)] ) - - let expectation = self.expectation(description: "Buffer Written") - + + var completion: Any? = nil + SSHClient.dial(MockCredentials.wrongHost.host, with: config) - .sink(receiveCompletion: { completion in - switch completion { - case .finished: - XCTFail("Authentication should not have succeeded") - case .failure(let error as SSHError): - dump(error) - if error == .connError(msg: "") { - expectation.fulfill() - } else { - XCTFail("Unknown error") - } - case .failure(_): - XCTFail("It should present an error of type SSHError.connError(msg:)") + .sink( + test: self, + receiveCompletion: { + completion = $0 + }, receiveValue: { _ in + XCTFail("Should not have received a connection") } - }, receiveValue: { _ in - XCTFail("Should not have received a connection") - }).store(in: &cancellableBag) + ) - waitForExpectations(timeout: 5, handler: nil) + __assertCompletionFailure(completion, withError: .connError(msg: "")) } /** Trying to authenticate against a host with either incorrect username or password credentials */ - func testAuthFailed() throws { - + func testAuthFailed() { let authMethods = [AuthPassword(with: MockCredentials.wrongCredentials.password)] let config = SSHClientConfig( @@ -135,35 +118,21 @@ class SSHErrorTests: XCTestCase { authMethods: authMethods ) - let expectation = self.expectation(description: "Buffer Written") - + var completion: Any? = nil + SSHClient.dial(MockCredentials.wrongCredentials.host, with: config) - .sink(receiveCompletion: { completion in - switch completion { - case .finished: - XCTFail("Authentication should not have succeeded") - case .failure(let error as SSHError): - - if error == .authFailed(methods: authMethods) { - expectation.fulfill() - } else { - XCTFail("Unknown error") - } - case .failure(_): - XCTFail("It should present an error of type SSHError.authFailed(methods:)") - - } + .sink( + test: self, + receiveCompletion: { + completion = $0 }, receiveValue: { _ in XCTFail("Should not have received a connection") - }).store(in: &cancellableBag) - - waitForExpectations(timeout: 10, handler: nil) + }) + __assertCompletionFailure(completion, withError: .authFailed(methods: authMethods)) } /** Given a wrong/fake IP it should fail as the host couldn't be translated to a usable IP. - - Uses the `SSHClient.urlToIpHostResolution(_:)` */ func testCouldntResolveHostAddress() throws { let config = SSHClientConfig( @@ -172,28 +141,18 @@ class SSHErrorTests: XCTestCase { authMethods: [AuthPassword(with: MockCredentials.password)] ) - let expectation = self.expectation(description: "Buffer Written") + var completion: Any? = nil SSHClient.dial(MockCredentials.incorrectIpHost, with: config) - .sink(receiveCompletion: { completion in - switch completion { - case .finished: - break - case .failure(let error as SSHError): - /// The given IP address couldn't be resolved into an IP address - expectation.fulfill() - - case .failure(let genericError): - XCTFail("Shouldn't have received an error that's not of type SSHError \(genericError.localizedDescription)") - } - }, receiveValue: { _ in - XCTFail("Shouldn't have received a connection") - }).store(in: &cancellableBag) + .sink( + test: self, + receiveCompletion: { + completion = $0 + }, + receiveValue: { _ in + XCTFail("Shouldn't have received a connection") + }) - waitForExpectations(timeout: 5, handler: nil) - } - - override func tearDown() { - cancellableBag.removeAll() + __assertCompletionFailure(completion, withError: .connError(msg: "Socket error: No such file or directory")) } } diff --git a/SSHTests/XCTestCase.swift b/SSHTests/XCTestCase.swift index 739c8193f..0f94b0898 100644 --- a/SSHTests/XCTestCase.swift +++ b/SSHTests/XCTestCase.swift @@ -56,12 +56,13 @@ extension XCTestCase { } extension Publisher { + func sink( test: XCTestCase, timeout: TimeInterval = 5, receiveCompletion: @escaping ((Subscribers.Completion) -> Void) = { _ in }, - receiveValue: @escaping ((Self.Output) -> Void) = {_ in } ) - { + receiveValue: @escaping ((Self.Output) -> Void) = {_ in } + ) { test.waitPublisher(self, timeout: timeout, receiveCompletion: receiveCompletion, receiveValue: receiveValue) } @@ -92,3 +93,13 @@ extension Publisher { return value } } + + +extension Subscribers.Completion { + var error: Error? { + switch self { + case .finished: return nil + case .failure(let err): return err + } + } +}