-
Notifications
You must be signed in to change notification settings - Fork 175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce timeout and after to support delayed verification. #434
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// | ||
// Continuation.swift | ||
// Cuckoo | ||
// | ||
// Created by Shoto Kobayashi on 03/09/2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol Continuation { | ||
var exitOnSuccess: Bool { get } | ||
|
||
func check() -> Bool | ||
|
||
func wait() | ||
|
||
func times(_ count: Int) -> VerificationSpec | ||
|
||
func never() -> VerificationSpec | ||
|
||
func atLeastOnce() -> VerificationSpec | ||
|
||
func atLeast(_ count: Int) -> VerificationSpec | ||
|
||
func atMost(_ count: Int) -> VerificationSpec | ||
|
||
func with(_ callMatcher: CallMatcher) -> VerificationSpec | ||
} | ||
|
||
public extension Continuation { | ||
func times(_ count: Int) -> VerificationSpec { | ||
VerificationSpec(callMatcher: Cuckoo.times(count), continuation: self) | ||
} | ||
|
||
func never() -> VerificationSpec { | ||
VerificationSpec(callMatcher: Cuckoo.times(0), continuation: self) | ||
} | ||
|
||
func atLeastOnce() -> VerificationSpec { | ||
VerificationSpec(callMatcher: Cuckoo.atLeast(1), continuation: self) | ||
} | ||
|
||
func atLeast(_ count: Int) -> VerificationSpec { | ||
VerificationSpec(callMatcher: Cuckoo.atLeast(count), continuation: self) | ||
} | ||
|
||
func atMost(_ count: Int) -> VerificationSpec { | ||
VerificationSpec(callMatcher: Cuckoo.atMost(count), continuation: self) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems to me like this one and every method above it can just call the |
||
} | ||
|
||
func with(_ callMatcher: CallMatcher) -> VerificationSpec { | ||
VerificationSpec(callMatcher: callMatcher, continuation: self) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// ContinuationAfterDelay.swift | ||
// Cuckoo | ||
// | ||
// Created by Shoto Kobayashi on 03/09/2022. | ||
// | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reduntant line. |
||
|
||
import Foundation | ||
|
||
public class ContinueationAfterDelay: NSObject, ContinuationWrapper { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo "Continueation". |
||
public let wrappedContinuation: ContinuationOverTime | ||
|
||
public init(delayDuration: TimeInterval, waitingDuration: TimeInterval) { | ||
wrappedContinuation = ContinuationOverTime(duration: delayDuration, waitingDuration: waitingDuration, exitOnSuccess: false) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// | ||
// ContinuationFunctions.swift | ||
// Cuckoo | ||
// | ||
// Created by Shoto Kobayashi on 03/09/2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public func timeout(_ timeoutDuration: TimeInterval, waitingDuration: TimeInterval = 0.01) -> ContinuationWithTimeout { | ||
ContinuationWithTimeout( | ||
timeoutDuration: timeoutDuration, | ||
waitingDuration: waitingDuration | ||
) | ||
} | ||
|
||
public func after(_ delayDuration: TimeInterval, waitingDuration: TimeInterval = 0.01) -> ContinueationAfterDelay { | ||
ContinueationAfterDelay( | ||
delayDuration: delayDuration, | ||
waitingDuration: waitingDuration | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// | ||
// ContinuationOnlyOnce.swift | ||
// Cuckoo | ||
// | ||
// Created by Shoto Kobayashi on 03/09/2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public class ContinuationOnlyOnce: NSObject, Continuation { | ||
public let exitOnSuccess = true | ||
|
||
private var isAlreadyChecked = false | ||
|
||
public override init() { | ||
super.init() | ||
} | ||
|
||
public func check() -> Bool { | ||
guard !isAlreadyChecked else { | ||
return false | ||
} | ||
isAlreadyChecked = true | ||
return true | ||
} | ||
|
||
public func wait() { | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// | ||
// ContinuationOverTime.swift | ||
// Cuckoo | ||
// | ||
// Created by Shoto Kobayashi on 03/09/2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public class ContinuationOverTime: NSObject, Continuation { | ||
public let duration: TimeInterval | ||
public let waitingDuration: TimeInterval | ||
public let exitOnSuccess: Bool | ||
|
||
private var start: Date? | ||
|
||
public init(duration: TimeInterval, waitingDuration: TimeInterval, exitOnSuccess: Bool) { | ||
self.duration = duration | ||
self.waitingDuration = waitingDuration | ||
self.exitOnSuccess = exitOnSuccess | ||
super.init() | ||
} | ||
|
||
public func check() -> Bool { | ||
if start == nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please bind |
||
start = Date() | ||
} | ||
return -start!.timeIntervalSinceNow <= duration | ||
} | ||
|
||
public func wait() { | ||
Thread.sleep(forTimeInterval: waitingDuration) | ||
} | ||
|
||
public func times(_ count: Int) -> VerificationSpec { | ||
VerificationSpec(callMatcher: Cuckoo.times(count), continuation: self) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// | ||
// ContinuationWithTimeout.swift | ||
// Cuckoo | ||
// | ||
// Created by Shoto Kobayashi on 03/09/2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public class ContinuationWithTimeout: NSObject, ContinuationWrapper { | ||
public let wrappedContinuation: ContinuationOverTime | ||
|
||
public init(timeoutDuration: TimeInterval, waitingDuration: TimeInterval) { | ||
wrappedContinuation = ContinuationOverTime(duration: timeoutDuration, waitingDuration: waitingDuration, exitOnSuccess: true) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// | ||
// ContinuationWrapper.swift | ||
// Cuckoo | ||
// | ||
// Created by Shoto Kobayashi on 03/09/2022. | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol ContinuationWrapper: Continuation { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this type necessary? |
||
associatedtype WrappedContinuation: Continuation | ||
|
||
var wrappedContinuation: WrappedContinuation { get } | ||
} | ||
|
||
public extension ContinuationWrapper { | ||
var exitOnSuccess: Bool { | ||
wrappedContinuation.exitOnSuccess | ||
} | ||
|
||
func check() -> Bool { | ||
wrappedContinuation.check() | ||
} | ||
|
||
func wait() { | ||
wrappedContinuation.wait() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,33 +11,44 @@ public struct CallMatcher { | |
public let name: String | ||
|
||
private let matchesFunction: ([StubCall]) -> Bool | ||
private let canRecoverFromFailureFunction: ([StubCall]) -> Bool | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this necessary? |
||
|
||
public init(name: String, matchesFunction: @escaping ([StubCall]) -> Bool) { | ||
public init(name: String, matchesFunction: @escaping ([StubCall]) -> Bool, canRecoverFromFailureFunction: @escaping ([StubCall]) -> Bool) { | ||
self.name = name | ||
self.matchesFunction = matchesFunction | ||
self.canRecoverFromFailureFunction = canRecoverFromFailureFunction | ||
} | ||
|
||
public init(name: String, numberOfExpectedCalls: Int, compareCallsFunction: @escaping (_ expected: Int, _ actual: Int) -> Bool) { | ||
self.init(name: name) { | ||
return compareCallsFunction(numberOfExpectedCalls, $0.count) | ||
|
||
public init( | ||
name: String, | ||
numberOfExpectedCalls: Int, | ||
compareCallsFunction: @escaping (_ expected: Int, _ actual: Int) -> Bool, | ||
canRecoverFromFailureFunction: @escaping (_ expected: Int, _ actual: Int) -> Bool | ||
) { | ||
self.init(name: name, matchesFunction: { compareCallsFunction(numberOfExpectedCalls, $0.count) }) { | ||
canRecoverFromFailureFunction(numberOfExpectedCalls, $0.count) | ||
} | ||
} | ||
|
||
public func matches(_ calls: [StubCall]) -> Bool { | ||
return matchesFunction(calls) | ||
} | ||
|
||
public func canRecoverFromFailure(_ calls: [StubCall]) -> Bool { | ||
canRecoverFromFailureFunction(calls) | ||
} | ||
|
||
public func or(_ otherMatcher: CallMatcher) -> CallMatcher { | ||
let name = "either \(self.name) or \(otherMatcher.name)" | ||
return CallMatcher(name: name) { | ||
return self.matches($0) || otherMatcher.matches($0) | ||
return CallMatcher(name: name, matchesFunction: { self.matches($0) || otherMatcher.matches($0) }) { | ||
self.canRecoverFromFailure($0) || otherMatcher.canRecoverFromFailureFunction($0) | ||
} | ||
} | ||
|
||
public func and(_ otherMatcher: CallMatcher) -> CallMatcher { | ||
let name = "both \(self.name) and \(otherMatcher.name)" | ||
return CallMatcher(name: name) { | ||
return self.matches($0) && otherMatcher.matches($0) | ||
return CallMatcher(name: name, matchesFunction: { self.matches($0) && otherMatcher.matches($0) }) { | ||
self.canRecoverFromFailure($0) && otherMatcher.canRecoverFromFailureFunction($0) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why opt for duplicate
init
instead of a default parameter value?