-
Notifications
You must be signed in to change notification settings - Fork 582
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
Deadlock in inline snapshot testing #820
Comments
@groue The main thread requirement is from XCTest's observer registration. XCTest has a bunch of hidden, main thread requirements that, when done from a non-main thread, cause an XCTest run to raise an exception. We could make the API for installing the test observer public in cases where someone needs to execute their first snapshot test on a non-main thread, but ideally things would remain transparent. Do you have any alternate ideas for ensuring this observer registration code runs on the main thread? |
Hi @stephencelis, thanks for the explanation :-) Maybe replacing the
I also contemplate this ideal :-) Considering my first paragraph, and |
We still need to register it synchronously on the main thread, though, so wouldn't this have the same problem if you're on a non-main thread but being synchronously dispatched to from the main thread? Or maybe I'm forgetting some of the specifics of dispatch here.
XCTest might! But I'd be surprised if it sees much iteration with swift-testing being worked on.
Linux supports test observers just fine, so should not have much to worry about here 😄 |
I was considering something like this: private let installTestObserver: Void = {
final class InlineSnapshotObserver: NSObject, XCTestObservation {
func testBundleDidFinish(_ testBundle: Bundle) {
writeInlineSnapshots()
}
}
// XCTest has a bunch of hidden, main thread requirements that, when done
// from a non-main thread, cause an XCTest run to raise an exception. This
// is one of them.
let observer = InlineSnapshotObserver()
if Thread.isMainThread {
XCTestObservationCenter.shared.addTestObserver(observer)
} else {
// Might dead-lock. Still looking for a nice workaround.
DispatchQueue.main.sync {
XCTestObservationCenter.shared.addTestObserver(observer)
}
}
}() This would work in the sample code below, because
func test_something() {
// On main thread
let queue = DispatchQueue(...)
queue.sync {
// In `queue`, but still on main thread: no deadlock
assertInlineSnapshot(...)
}
}
Fair point :-) |
Hello,
Happy new year :-)
I'm not sure if this is a bug report or a request for advice. But I could notice that inline snapshot testing can deadlock.
The first call to
assertInlineSnapshot
initializes aInlineSnapshotObserver
: https://github.com/pointfreeco/swift-snapshot-testing/blob/1.15.1/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift#L270-L279This initialization is protected by
DispatchQueue.mainSync
that checks for the current dispatch queue: https://github.com/pointfreeco/swift-snapshot-testing/blob/1.15.1/Sources/InlineSnapshotTesting/AssertInlineSnapshot.swift#L285-L292If, unfortunately, the first call to
assertInlineSnapshot
is made, synchronously, from a dispatch queue which is not the main queue, we have a deadlock:Maybe snapshot testing MUST be done from the main thread, and the above test is illegal?
Or maybe not? Indeed, dispatch queues are a valid way to protect access to shared mutable resources, and testing such resources is easier when the test can be executed right from such dispatch queue.
What would you suggest?
The text was updated successfully, but these errors were encountered: