1010 *******************************************************************************/
1111package org .eclipse .rdf4j .repository .sparql ;
1212
13- import static org .assertj .core .api .Assertions .fail ;
13+ import static org .assertj .core .api .Assertions .assertThat ;
1414
15- import java .util .concurrent .CountDownLatch ;
15+ import java .lang .reflect .Field ;
16+ import java .util .concurrent .ExecutorService ;
1617import java .util .concurrent .TimeUnit ;
1718
19+ import org .eclipse .rdf4j .http .client .SharedHttpClientSessionManager ;
1820import org .eclipse .rdf4j .repository .RepositoryConnection ;
19- import org .eclipse .rdf4j .repository .RepositoryException ;
2021import org .junit .jupiter .api .Test ;
2122
2223/**
@@ -31,42 +32,33 @@ public class SPARQLRepositoryCleanerTest {
3132
3233 @ Test
3334 void autoShutdownOnUnreachable () throws Exception {
34- CountDownLatch shutdownInvoked = new CountDownLatch ( 1 );
35+ SPARQLRepository repo = new SPARQLRepository ( "http://example.org/sparql" );
3536
36- runRepo (shutdownInvoked );
37-
38- // Encourage GC and wait briefly for cleaner to run
39- boolean observed = false ;
40- for (int i = 0 ; i < 20 && !observed ; i ++) {
41- System .gc ();
42- System .runFinalization ();
43- observed = shutdownInvoked .await (250 , TimeUnit .MILLISECONDS );
37+ // Ensure dependent client is created
38+ try (RepositoryConnection conn = repo .getConnection ()) {
39+ // no-op
4440 }
4541
46- if (!observed ) {
47- fail ("Expected shutDownInternal() to be invoked when SPARQLRepository became unreachable" );
48- }
49- }
42+ SharedHttpClientSessionManager mgr = (SharedHttpClientSessionManager ) repo .getHttpClientSessionManager ();
5043
51- private static void runRepo (CountDownLatch shutdownInvoked ) {
52- // Create a repository instance that signals when shutDownInternal() is invoked
53- SPARQLRepository repo = new SPARQLRepository ("http://example.org/sparql" ) {
54- @ Override
55- protected void shutDownInternal () throws RepositoryException {
56- try {
57- super .shutDownInternal ();
58- } finally {
59- shutdownInvoked .countDown ();
60- }
61- }
62- };
44+ // Access internal executor to verify shutdown state
45+ Field f = SharedHttpClientSessionManager .class .getDeclaredField ("executor" );
46+ f .setAccessible (true );
47+ ExecutorService exec = (ExecutorService ) f .get (mgr );
6348
64- // Exercise minimal usage without hitting the network
65- try (RepositoryConnection conn = repo .getConnection ()) {
66- // no-op
49+ // Drop strong reference and encourage GC to trigger Cleaner
50+ repo = null ;
51+
52+ boolean cleaned = false ;
53+ for (int i = 0 ; i < 40 && !cleaned ; i ++) {
54+ System .gc ();
55+ System .runFinalization ();
56+ TimeUnit .MILLISECONDS .sleep (100 );
57+ cleaned = exec .isShutdown () || exec .isTerminated ();
6758 }
6859
69- // Drop strong reference and ask GC to collect
70- repo = null ;
60+ assertThat (cleaned )
61+ .as ("dependent session manager executor should be shut down by Cleaner" )
62+ .isTrue ();
7163 }
7264}
0 commit comments