Skip to content

Commit e045ad5

Browse files
committed
Fix a race condition that can cause testDontReturnEmptyDiagnosticsIfDiagnosticRequestIsCancelled to fail
`testDontReturnEmptyDiagnosticsIfDiagnosticRequestIsCancelled` assumed that cancelling the request cancels the target preparation but that is not true. If we only handle the request cancellation after we started preparing the target, the test would time out. The only reason why we had the target preparation wait in here was to ensure that we cannot finish the request handling before the request cancellation gets handled. We can achieve a similar result by using an example that is hard to typecheck. rdar://148654514
1 parent 67a16e6 commit e045ad5

File tree

1 file changed

+24
-28
lines changed

1 file changed

+24
-28
lines changed

Tests/SourceKitLSPTests/PullDiagnosticsTests.swift

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -329,37 +329,34 @@ final class PullDiagnosticsTests: XCTestCase {
329329
}
330330

331331
func testDontReturnEmptyDiagnosticsIfDiagnosticRequestIsCancelled() async throws {
332-
let diagnosticRequestCancelled = MultiEntrySemaphore(name: "diagnostic request cancelled")
333-
let packageLoadingDidFinish = self.expectation(description: "Package loading did finish")
334-
var testHooks = Hooks()
335-
testHooks.buildSystemHooks.swiftPMTestHooks.reloadPackageDidFinish = {
336-
packageLoadingDidFinish.fulfill()
337-
}
338-
testHooks.indexHooks.preparationTaskDidStart = { _ in
339-
await diagnosticRequestCancelled.waitOrXCTFail()
340-
// Poll until the `CancelRequestNotification` has been propagated to the request handling.
341-
// We can't use `repeatUntilExpectedResult` here because that throws a `CancellationError` when the preparation is
342-
// cancelled.
343-
for _ in 0..<Int(defaultTimeout * 100) {
344-
if Task.isCancelled {
345-
break
346-
}
347-
#if os(Windows)
348-
Sleep(10 /*ms*/)
349-
#else
350-
usleep(10_000 /*µs*/)
351-
#endif
352-
}
353-
}
332+
// Use an example that is slow to type check to ensure that we don't get a diagnostic response from sourcekitd
333+
// before the request cancellation gets handled.
354334
let project = try await SwiftPMTestProject(
355335
files: [
356-
"Lib.swift": "let x: String = 1"
336+
"Lib.swift": """
337+
struct A: ExpressibleByIntegerLiteral { init(integerLiteral value: Int) {} }
338+
struct B: ExpressibleByIntegerLiteral { init(integerLiteral value: Int) {} }
339+
struct C: ExpressibleByIntegerLiteral { init(integerLiteral value: Int) {} }
340+
341+
func + (lhs: A, rhs: B) -> A { fatalError() }
342+
func + (lhs: B, rhs: C) -> A { fatalError() }
343+
func + (lhs: C, rhs: A) -> A { fatalError() }
344+
345+
func + (lhs: B, rhs: A) -> B { fatalError() }
346+
func + (lhs: C, rhs: B) -> B { fatalError() }
347+
func + (lhs: A, rhs: C) -> B { fatalError() }
348+
349+
func + (lhs: C, rhs: B) -> C { fatalError() }
350+
func + (lhs: B, rhs: C) -> C { fatalError() }
351+
func + (lhs: A, rhs: A) -> C { fatalError() }
352+
353+
func slow() {
354+
let x: C = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
355+
}
356+
"""
357357
],
358-
hooks: testHooks,
359-
enableBackgroundIndexing: true,
360-
pollIndex: false
358+
enableBackgroundIndexing: false
361359
)
362-
try await fulfillmentOfOrThrow(packageLoadingDidFinish)
363360
let (uri, _) = try project.openDocument("Lib.swift")
364361

365362
let diagnosticResponseReceived = self.expectation(description: "Received diagnostic response")
@@ -370,7 +367,6 @@ final class PullDiagnosticsTests: XCTestCase {
370367
diagnosticResponseReceived.fulfill()
371368
}
372369
project.testClient.send(CancelRequestNotification(id: requestID))
373-
diagnosticRequestCancelled.signal()
374370
try await fulfillmentOfOrThrow(diagnosticResponseReceived)
375371
}
376372

0 commit comments

Comments
 (0)