@@ -108,9 +108,9 @@ final class CrashRecoveryTests: XCTestCase {
108
108
/// Crashes clangd and waits for it to restart
109
109
/// - Parameters:
110
110
/// - ws: The workspace for which the clangd server shall be crashed
111
- /// - loc: A test location that points to the first line of a given file. This line needs to be otherwise empty.
112
- private func crashClangd( for ws: SKTibsTestWorkspace , firstLineLoc loc : TestLocation ) {
113
- let clangdServer = ws. testServer. server!. _languageService ( for: loc . docUri, . cpp, in: ws. testServer. server!. workspace!) !
111
+ /// - document: The URI of a C/C++/... document in the workspace
112
+ private func crashClangd( for ws: SKTibsTestWorkspace , document docUri : DocumentURI ) {
113
+ let clangdServer = ws. testServer. server!. _languageService ( for: docUri, . cpp, in: ws. testServer. server!. workspace!) !
114
114
115
115
let clangdCrashed = self . expectation ( description: " clangd crashed " )
116
116
let clangdRestarted = self . expectation ( description: " clangd restarted " )
@@ -126,21 +126,13 @@ final class CrashRecoveryTests: XCTestCase {
126
126
}
127
127
}
128
128
129
- // Add a pragma to crash clang
130
- let addCrashPragma = TextDocumentContentChangeEvent ( range: loc. position..< loc. position, rangeLength: 0 , text: " #pragma clang __debug crash \n " )
131
- ws. sk. send ( DidChangeTextDocumentNotification ( textDocument: VersionedTextDocumentIdentifier ( loc. docUri, version: 3 ) , contentChanges: [ addCrashPragma] ) )
129
+ clangdServer. _crash ( )
132
130
133
131
self . wait ( for: [ clangdCrashed] , timeout: 5 )
134
-
135
- // Once clangds has crashed, remove the pragma again to allow it to restart
136
- let removeCrashPragma = TextDocumentContentChangeEvent ( range: loc. position..< Position ( line: 1 , utf16index: 0 ) , rangeLength: 28 , text: " " )
137
- ws. sk. send ( DidChangeTextDocumentNotification ( textDocument: VersionedTextDocumentIdentifier ( loc. docUri, version: 4 ) , contentChanges: [ removeCrashPragma] ) )
138
-
139
132
self . wait ( for: [ clangdRestarted] , timeout: 30 )
140
133
}
141
134
142
135
func testClangdCrashRecovery( ) throws {
143
- throw XCTSkip ( " failing on rebranch - rdar://73717447 " )
144
136
try XCTSkipUnless ( longTestsEnabled)
145
137
146
138
let ws = try ! staticSourceKitTibsWorkspace ( name: " ClangCrashRecovery " ) !
@@ -167,7 +159,7 @@ final class CrashRecoveryTests: XCTestCase {
167
159
168
160
// Crash clangd
169
161
170
- crashClangd ( for: ws, firstLineLoc : loc)
162
+ crashClangd ( for: ws, document : loc. docUri )
171
163
172
164
// Check that we have re-opened the document with the correct in-memory state
173
165
@@ -178,7 +170,6 @@ final class CrashRecoveryTests: XCTestCase {
178
170
}
179
171
180
172
func testClangdCrashRecoveryReopensWithCorrectBuildSettings( ) throws {
181
- throw XCTSkip ( " failing on rebranch - rdar://73717447 " )
182
173
try XCTSkipUnless ( longTestsEnabled)
183
174
184
175
let ws = try ! staticSourceKitTibsWorkspace ( name: " ClangCrashRecoveryBuildSettings " ) !
@@ -199,7 +190,7 @@ final class CrashRecoveryTests: XCTestCase {
199
190
200
191
// Crash clangd
201
192
202
- crashClangd ( for: ws, firstLineLoc : loc)
193
+ crashClangd ( for: ws, document : loc. docUri )
203
194
204
195
// Check that we have re-opened the document with the correct build settings
205
196
// If we did not recover the correct build settings, document highlight would
@@ -212,7 +203,6 @@ final class CrashRecoveryTests: XCTestCase {
212
203
}
213
204
214
205
func testPreventClangdCrashLoop( ) throws {
215
- throw XCTSkip ( " failing on rebranch - rdar://73717447 " )
216
206
try XCTSkipUnless ( longTestsEnabled)
217
207
218
208
let ws = try ! staticSourceKitTibsWorkspace ( name: " ClangCrashRecovery " ) !
@@ -231,53 +221,38 @@ final class CrashRecoveryTests: XCTestCase {
231
221
232
222
let clangdCrashed = self . expectation ( description: " clangd crashed " )
233
223
clangdCrashed. assertForOverFulfill = false
234
- // assertForOverFulfill is not working on Linux (SR-12575). Manually keep track if we have already called fulfill on the expectation
235
- var clangdCrashedFulfilled = false
236
224
237
225
let clangdRestartedFirstTime = self . expectation ( description: " clangd restarted for the first time " )
238
-
239
226
let clangdRestartedSecondTime = self . expectation ( description: " clangd restarted for the second time " )
240
- clangdRestartedSecondTime. assertForOverFulfill = false
241
- // assertForOverFulfill is not working on Linux (SR-12575). Manually keep track if we have already called fulfill on the expectation
242
- var clangdRestartedSecondTimeFulfilled = false
243
-
227
+
244
228
var clangdHasRestartedFirstTime = false
245
229
246
230
clangdServer. addStateChangeHandler { ( oldState, newState) in
247
231
switch newState {
248
232
case . connectionInterrupted:
249
- if !clangdCrashedFulfilled {
250
- clangdCrashed. fulfill ( )
251
- clangdCrashedFulfilled = true
252
- }
233
+ clangdCrashed. fulfill ( )
253
234
case . connected:
254
235
if !clangdHasRestartedFirstTime {
255
236
clangdRestartedFirstTime. fulfill ( )
256
237
clangdHasRestartedFirstTime = true
257
238
} else {
258
- if !clangdRestartedSecondTimeFulfilled {
259
- clangdRestartedSecondTime. fulfill ( )
260
- clangdRestartedSecondTimeFulfilled = true
261
- }
239
+ clangdRestartedSecondTime. fulfill ( )
262
240
}
263
241
default :
264
242
break
265
243
}
266
244
}
267
245
268
- // Add a pragma to crash clang
269
-
270
- let addCrashPragma = TextDocumentContentChangeEvent ( range: loc. position..< loc. position, rangeLength: 0 , text: " #pragma clang __debug crash \n " )
271
- ws. sk. send ( DidChangeTextDocumentNotification ( textDocument: VersionedTextDocumentIdentifier ( loc. docUri, version: 3 ) , contentChanges: [ addCrashPragma] ) )
246
+ clangdServer. _crash ( )
272
247
273
248
self . wait ( for: [ clangdCrashed] , timeout: 5 )
274
-
275
- // Clangd has crashed for the first time. Leave the pragma there to crash clangd once again.
276
-
277
249
self . wait ( for: [ clangdRestartedFirstTime] , timeout: 30 )
278
250
// Clangd has restarted. Note the date so we can check that the second restart doesn't happen too quickly.
279
251
let firstRestartDate = Date ( )
280
-
252
+
253
+ // Crash clangd again. This time, it should only restart after a delay.
254
+ clangdServer. _crash ( )
255
+
281
256
self . wait ( for: [ clangdRestartedSecondTime] , timeout: 30 )
282
257
XCTAssert ( Date ( ) . timeIntervalSince ( firstRestartDate) > 5 , " Clangd restarted too quickly after crashing twice in a row. We are not preventing crash loops. " )
283
258
}
0 commit comments