3939import org .junit .jupiter .api .BeforeAll ;
4040import org .junit .jupiter .api .BeforeEach ;
4141import org .junit .jupiter .api .Tag ;
42+ import org .junit .jupiter .api .Test ;
4243import org .junit .jupiter .api .parallel .Execution ;
4344import org .junit .jupiter .api .parallel .ExecutionMode ;
4445import org .junit .jupiter .params .ParameterizedTest ;
@@ -127,7 +128,7 @@ public void shutdownDuringValidation(int sleepMillis) {
127128 commitAndExpect (connection , EXPECTED_REPOSITORY_SIZE , 0 );
128129
129130 } catch (RepositoryException e ) {
130- if (e . getCause () instanceof InterruptedException ) {
131+ if (causedByInterruptedException ( e ) ) {
131132 return ;
132133 }
133134 logger .error ("Error during test execution" , e );
@@ -146,15 +147,15 @@ public void shutdownDuringValidation(int sleepMillis) {
146147 }
147148
148149 } catch (RepositoryException e ) {
149- if (e . getCause () instanceof InterruptedException ) {
150+ if (causedByInterruptedException ( e ) ) {
150151 // ignore this exception
151152 return ;
152153 } else {
153154 throw e ;
154155 }
155156 }
156157 } catch (Exception e ) {
157- if (e instanceof RepositoryException && e . getCause () instanceof InterruptedException ) {
158+ if (e instanceof RepositoryException && causedByInterruptedException ( e ) ) {
158159 System .out .println (e );
159160 return ;
160161 }
@@ -193,7 +194,7 @@ public void shutdownDuringValidationTransactional(int sleepMillis) {
193194
194195 commitAndExpect (connection , EXPECTED_REPOSITORY_SIZE + 1 , 1 );
195196 } catch (RepositoryException e ) {
196- if (e . getCause () instanceof InterruptedException ) {
197+ if (causedByInterruptedException ( e ) ) {
197198 // ignore this exception
198199 return ;
199200 }
@@ -211,15 +212,15 @@ public void shutdownDuringValidationTransactional(int sleepMillis) {
211212 .isIn (0L , 1L , (long ) (EXPECTED_REPOSITORY_SIZE + 1 ));
212213
213214 } catch (RepositoryException e ) {
214- if (e . getCause () instanceof InterruptedException ) {
215+ if (causedByInterruptedException ( e ) ) {
215216 // ignore this exception
216217 return ;
217218 } else {
218219 throw e ;
219220 }
220221 }
221222 } catch (Exception e ) {
222- if (e instanceof RepositoryException && e . getCause () instanceof InterruptedException ) {
223+ if (e instanceof RepositoryException && causedByInterruptedException ( e ) ) {
223224 System .out .println (e );
224225 return ;
225226 }
@@ -256,7 +257,7 @@ public void shutdownDuringValidationFailure(int sleepMillis) {
256257
257258 commitAndExpect (connection , 0 , 0 );
258259 } catch (RepositoryException e ) {
259- if (e . getCause () instanceof InterruptedException ) {
260+ if (causedByInterruptedException ( e ) ) {
260261 // ignore this exception
261262 return ;
262263 }
@@ -270,15 +271,15 @@ public void shutdownDuringValidationFailure(int sleepMillis) {
270271 assertEquals (0 , size ,
271272 "The repository should be empty because the transaction always fails validation." );
272273 } catch (RepositoryException e ) {
273- if (e . getCause () instanceof InterruptedException ) {
274+ if (causedByInterruptedException ( e ) ) {
274275 // ignore this exception
275276 return ;
276277 } else {
277278 throw e ;
278279 }
279280 }
280281 } catch (Exception e ) {
281- if (e instanceof RepositoryException && e . getCause () instanceof InterruptedException ) {
282+ if (e instanceof RepositoryException && causedByInterruptedException ( e ) ) {
282283 System .out .println (e );
283284 return ;
284285 }
@@ -314,7 +315,7 @@ public void shutdownDuringValidationFailureNonParallel(int sleepMillis) {
314315
315316 commitAndExpect (connection , 0 , 0 );
316317 } catch (RepositoryException e ) {
317- if (e . getCause () instanceof InterruptedException ) {
318+ if (causedByInterruptedException ( e ) ) {
318319 // ignore this exception
319320 return ;
320321 }
@@ -329,15 +330,15 @@ public void shutdownDuringValidationFailureNonParallel(int sleepMillis) {
329330 assertEquals (0 , size ,
330331 "The repository should be empty because the transaction always fails validation." );
331332 } catch (RepositoryException e ) {
332- if (e . getCause () instanceof InterruptedException ) {
333+ if (causedByInterruptedException ( e ) ) {
333334 // ignore this exception
334335 return ;
335336 } else {
336337 throw e ;
337338 }
338339 }
339340 } catch (Exception e ) {
340- if (e instanceof RepositoryException && e . getCause () instanceof InterruptedException ) {
341+ if (e instanceof RepositoryException && causedByInterruptedException ( e ) ) {
341342 System .out .println (e );
342343 return ;
343344 }
@@ -382,7 +383,7 @@ public void shutdownDuringValidationTransactionalNonParallel(int sleepMillis) {
382383 // ignore this exception
383384 return ;
384385 }
385- if (e . getCause () instanceof InterruptedException ) {
386+ if (causedByInterruptedException ( e ) ) {
386387 // ignore this exception
387388 return ;
388389 }
@@ -403,15 +404,15 @@ public void shutdownDuringValidationTransactionalNonParallel(int sleepMillis) {
403404 .as ("Repository size" )
404405 .isIn (0L , 1L , (long ) (EXPECTED_REPOSITORY_SIZE + 1 ));
405406 } catch (RepositoryException e ) {
406- if (e . getCause () instanceof InterruptedException ) {
407+ if (causedByInterruptedException ( e ) ) {
407408 // ignore this exception
408409 return ;
409410 } else {
410411 throw e ;
411412 }
412413 }
413414 } catch (Exception e ) {
414- if (e instanceof RepositoryException && e . getCause () instanceof InterruptedException ) {
415+ if (e instanceof RepositoryException && causedByInterruptedException ( e ) ) {
415416 System .out .println (e );
416417 return ;
417418 }
@@ -427,6 +428,40 @@ public void shutdownDuringValidationTransactionalNonParallel(int sleepMillis) {
427428 }
428429 }
429430
431+ @ Test
432+ void nestedInterruptedExceptionShouldBeDetected () {
433+ InterruptedException interruptedException = new InterruptedException ("nested" );
434+ SailException sailException = new SailException ("wrapper" , new SailException ("inner" , interruptedException ));
435+ RepositoryException repositoryException = new RepositoryException ("top" , sailException );
436+
437+ boolean handled = causedByInterruptedException (repositoryException );
438+
439+ assertThat (handled ).as ("Should detect nested InterruptedException" ).isTrue ();
440+ }
441+
442+ private static boolean causedByInterruptedException (Throwable throwable ) {
443+ return causedByInterruptedExceptionRecursion (throwable , 10 );
444+ }
445+
446+ private static boolean causedByInterruptedExceptionRecursion (Throwable throwable , int maxDepth ) {
447+ if (maxDepth < 0 ) {
448+ throw new IllegalStateException ("Too deep" );
449+ }
450+ if (throwable == null ) {
451+ return false ;
452+ }
453+ if (throwable instanceof InterruptedException ) {
454+ return true ;
455+ }
456+ if (throwable instanceof InterruptedSailException ) {
457+ return true ;
458+ }
459+ if (throwable .getCause () == throwable ) {
460+ return false ;
461+ }
462+ return causedByInterruptedExceptionRecursion (throwable .getCause (), maxDepth - 1 );
463+ }
464+
430465 private static void commitAndExpect (SailRepositoryConnection connection , long expected , long failedExpected ) {
431466 try {
432467 connection .commit ();
@@ -442,9 +477,7 @@ private static void commitAndExpect(SailRepositoryConnection connection, long ex
442477 try {
443478 connection .rollback ();
444479 } catch (Exception e ) {
445- if (e .getCause () instanceof InterruptedException ) {
446- // ignore this exception
447- } else if (e .getCause () != null && e .getCause ().getCause () instanceof InterruptedException ) {
480+ if (causedByInterruptedException (e )) {
448481 // ignore this exception
449482 } else {
450483 throw e ;
0 commit comments