1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
import XCTest
@testable import WIT
class RequestEvaluatorTests: XCTestCase {
struct MyRequest<T>: EvaluationRequest {
let key: Int
let evaluate: (Evaluator) throws -> T
init(key: Int, evaluate: @escaping (Evaluator) throws -> T = { _ in }) {
self.key = key
self.evaluate = evaluate
}
func evaluate(evaluator: Evaluator) throws -> T {
return try self.evaluate(evaluator)
}
static func == (lhs: MyRequest, rhs: MyRequest) -> Bool {
return lhs.key == rhs.key
}
func hash(into hasher: inout Hasher) {
hasher.combine(key)
}
}
struct MyError: Error {}
func testMemoization() throws {
var invoked = 0
let request = MyRequest(key: 1) { _ in
invoked += 1
return invoked
}
let evaluator = Evaluator()
XCTAssertEqual(try evaluator.evaluate(request: request), 1)
// Ensure it returns the same value
XCTAssertEqual(try evaluator.evaluate(request: request), 1)
// Ensure the evaluation method is called only once
XCTAssertEqual(invoked, 1)
}
func testCycleDetection() throws {
let evaluator = Evaluator()
var anyError: Error?
XCTAssertThrowsError(
try evaluator.evaluate(
request: MyRequest(
key: 1,
evaluate: {
try $0.evaluate(
request: MyRequest(
key: 2,
evaluate: {
try $0.evaluate(request: MyRequest(key: 1)) // again request key=1
}))
})),
"CyclicalRequestError expected",
{ anyError = $0 }
)
let cyclicalRequestError = try XCTUnwrap(anyError as? Evaluator.CyclicalRequestError)
XCTAssertEqual(cyclicalRequestError.activeRequests.count, 3)
}
func testThrowingRequest() throws {
var invoked = 0
let request = MyRequest(key: 1) { _ in
invoked += 1
throw MyError()
}
let evaluator = Evaluator()
XCTAssertThrowsError(try evaluator.evaluate(request: request))
XCTAssertThrowsError(try evaluator.evaluate(request: request))
// Ensure the evaluation method is called only once even though
// the request throws error
XCTAssertEqual(invoked, 1)
}
}
|