9
public final class TestTimeoutTrackingTestRunnerSream: TestRunnerStream {
10
struct LastStartedTestInfo {
11
let testName: TestName
12
let testStartedAt: DateSince1970ReferenceDate
15
private let dateProvider: DateProvider
16
private let detectedLongRunningTest: (TestName, DateSince1970ReferenceDate) -> ()
17
private let lastStartedTestInfo = AtomicValue<LastStartedTestInfo?>(nil)
18
private let logger: () -> ContextualLogger
19
private let maximumTestDuration: TimeInterval
20
private let pollPeriod: DispatchTimeInterval
21
private var testHangTrackingTimer: DispatchBasedTimer?
24
dateProvider: DateProvider,
25
detectedLongRunningTest: @escaping (TestName, DateSince1970ReferenceDate) -> (),
26
logger: @escaping () -> ContextualLogger,
27
maximumTestDuration: TimeInterval,
28
pollPeriod: DispatchTimeInterval
30
self.dateProvider = dateProvider
31
self.detectedLongRunningTest = detectedLongRunningTest
33
self.maximumTestDuration = maximumTestDuration
34
self.pollPeriod = pollPeriod
37
public func openStream() {}
39
public func testStarted(testName: TestName) {
40
startMonitoringForHangs(testName: testName)
43
public func caughtException(testException: TestException) {}
45
public func logCaptured(entry: TestLogEntry) {}
47
public func testStopped(testStoppedEvent: TestStoppedEvent) {
48
stopMonitoringForHangs(testStoppedEvent: testStoppedEvent)
51
public func closeStream() {
55
private func startMonitoringForHangs(testName: TestName) {
56
lastStartedTestInfo.set(
57
LastStartedTestInfo(testName: testName, testStartedAt: dateProvider.dateSince1970ReferenceDate())
60
testHangTrackingTimer = DispatchBasedTimer.startedTimer(repeating: pollPeriod, leeway: pollPeriod) { [weak self] timer in
61
guard let strongSelf = self else { return timer.stop() }
62
guard let lastStartedTestInfo = strongSelf.lastStartedTestInfo.currentValue() else { return timer.stop() }
64
if strongSelf.dateProvider.currentDate().timeIntervalSince(lastStartedTestInfo.testStartedAt.date) > strongSelf.maximumTestDuration {
65
strongSelf.didDetectLongRunningTest(lastStartedTestInfo: lastStartedTestInfo)
70
logger().trace("Started monitoring duration of test \(testName)")
73
private func stopMonitoringForHangs(testStoppedEvent: TestStoppedEvent) {
76
logger().trace("Stopped monitoring duration of test \(testStoppedEvent.testName), test finished with result \(testStoppedEvent.result)")
79
private func didDetectLongRunningTest(lastStartedTestInfo: LastStartedTestInfo) {
80
logger().warning("Detected a long running test: \(lastStartedTestInfo.testName) was running for more than \(maximumTestDuration.loggableInSeconds()), test started at: \(lastStartedTestInfo.testStartedAt.date.loggable())")
82
detectedLongRunningTest(lastStartedTestInfo.testName, lastStartedTestInfo.testStartedAt)
85
private func stopTimer() {
86
lastStartedTestInfo.set(nil)
87
testHangTrackingTimer?.stop()
88
testHangTrackingTimer = nil