Skip to content

Instantly share code, notes, and snippets.

@rudolf-adamkovic
Last active December 3, 2017 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rudolf-adamkovic/a37dbc4fda13700e65309503b9a676a7 to your computer and use it in GitHub Desktop.
Save rudolf-adamkovic/a37dbc4fda13700e65309503b9a676a7 to your computer and use it in GitHub Desktop.
PreconditionFailable protocol
/* PRODUCTION */
protocol PreconditionFailable {
associatedtype PreconditionFailure
}
extension PreconditionFailable {
static func precondition(_ condition: Bool, _ message: PreconditionFailure) {
guard !condition else { return }
PreconditionFailureHandler.trap(String(describing: message))
RunLoop.spin()
}
static func preconditionFailure(_ message: PreconditionFailure) -> Never {
PreconditionFailureHandler.trap(String(describing: message))
RunLoop.spin()
}
}
struct PreconditionFailureHandler {
static var trap: (String) -> Void = { message in
fatalError(message)
}
}
/* TESTING */
protocol PreconditionFailableTesting {
associatedtype PreconditionFailableType: PreconditionFailable
}
extension PreconditionFailableTesting where Self: XCTestCase {
func expectPreconditionFailure(
_ expectedFailure: PreconditionFailableType.PreconditionFailure,
file: StaticString = #file,
line: UInt = #line,
trigger: @escaping () -> Void
) {
let failureExpectation = expectation(description: "Precondition failure testing expectation")
let originalTrap = PreconditionFailureHandler.trap
PreconditionFailureHandler.trap = { message in
XCTAssertEqual(message, String(describing: expectedFailure), file: file, line: line)
failureExpectation.fulfill()
RunLoop.spin()
}
DispatchQueue(label: "Precondition failure testing queue").async(execute: trigger)
waitForExpectations(timeout: 1) { error in
if error != nil {
let failureDescription = String(describing: expectedFailure)
XCTFail("Precondition failure: " + failureDescription, file: file, line: line)
}
}
PreconditionFailureHandler.trap = originalTrap
}
}
/* UTILITIES */
extension RunLoop {
static func spin() -> Never {
repeat {
RunLoop.current.run()
} while (true)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment