1
1
package org .testcontainers .junit .jupiter ;
2
2
3
+ import java .util .concurrent .ConcurrentHashMap ;
4
+ import java .util .concurrent .atomic .AtomicInteger ;
3
5
import lombok .Getter ;
4
6
import org .junit .jupiter .api .extension .AfterAllCallback ;
5
7
import org .junit .jupiter .api .extension .AfterEachCallback ;
23
25
import org .testcontainers .lifecycle .TestLifecycleAware ;
24
26
25
27
import java .lang .reflect .Field ;
26
- import java .lang .reflect .Method ;
27
28
import java .util .LinkedHashSet ;
28
29
import java .util .List ;
29
30
import java .util .Optional ;
@@ -41,6 +42,7 @@ class TestcontainersExtension implements BeforeEachCallback, BeforeAllCallback,
41
42
private static final String TEST_INSTANCE = "testInstance" ;
42
43
private static final String SHARED_LIFECYCLE_AWARE_CONTAINERS = "sharedLifecycleAwareContainers" ;
43
44
private static final String LOCAL_LIFECYCLE_AWARE_CONTAINERS = "localLifecycleAwareContainers" ;
45
+ private static final ConcurrentHashMap <String , StoreAdapterThread > STORE_ADAPTER_THREADS = new ConcurrentHashMap <>();
44
46
45
47
@ Override
46
48
public void postProcessTestInstance (final Object testInstance , final ExtensionContext context ) {
@@ -56,7 +58,7 @@ public void beforeAll(ExtensionContext context) {
56
58
Store store = context .getStore (NAMESPACE );
57
59
List <StoreAdapter > sharedContainersStoreAdapters = findSharedContainers (testClass );
58
60
59
- sharedContainersStoreAdapters .forEach (adapter -> store .getOrComputeIfAbsent (adapter .getKey (), k -> adapter . start ( )));
61
+ sharedContainersStoreAdapters .forEach (adapter -> store .getOrComputeIfAbsent (adapter .getKey (), k -> storeAdapterStart ( k , adapter )));
60
62
61
63
List <TestLifecycleAware > lifecycleAwareContainers = sharedContainersStoreAdapters
62
64
.stream ()
@@ -93,6 +95,20 @@ public void afterEach(ExtensionContext context) {
93
95
signalAfterTestToContainersFor (LOCAL_LIFECYCLE_AWARE_CONTAINERS , context );
94
96
}
95
97
98
+ private static synchronized StoreAdapter storeAdapterStart (String key , StoreAdapter adapter ) {
99
+ boolean isInitialized = STORE_ADAPTER_THREADS .containsKey (key );
100
+
101
+ if (!isInitialized ) {
102
+ StoreAdapter storeAdapter = adapter .start ();
103
+ STORE_ADAPTER_THREADS .put (key , new StoreAdapterThread (storeAdapter ));
104
+ return storeAdapter ;
105
+ }
106
+
107
+ StoreAdapterThread storeAdapter = STORE_ADAPTER_THREADS .get (key );
108
+ storeAdapter .threads .incrementAndGet ();
109
+ return storeAdapter .storeAdapter ;
110
+ }
111
+
96
112
private void signalBeforeTestToContainers (List <TestLifecycleAware > lifecycleAwareContainers , TestDescription testDescription ) {
97
113
lifecycleAwareContainers .forEach (container -> container .beforeTest (testDescription ));
98
114
}
@@ -229,9 +245,9 @@ private static StoreAdapter getContainerInstance(final Object testInstance, fina
229
245
private static class StoreAdapter implements CloseableResource {
230
246
231
247
@ Getter
232
- private String key ;
248
+ private final String key ;
233
249
234
- private Startable container ;
250
+ private final Startable container ;
235
251
236
252
private StoreAdapter (Class <?> declaringClass , String fieldName , Startable container ) {
237
253
this .key = declaringClass .getName () + "." + fieldName ;
@@ -245,7 +261,25 @@ private StoreAdapter start() {
245
261
246
262
@ Override
247
263
public void close () {
248
- container .stop ();
264
+ int total = STORE_ADAPTER_THREADS .getOrDefault (key , StoreAdapterThread .NULL ).threads .decrementAndGet ();
265
+ if (total < 1 ) {
266
+ container .stop ();
267
+ STORE_ADAPTER_THREADS .remove (key );
268
+ }
269
+ }
270
+
271
+ }
272
+
273
+ private static class StoreAdapterThread {
274
+
275
+ public static final StoreAdapterThread NULL = new StoreAdapterThread (null );
276
+ public final StoreAdapter storeAdapter ;
277
+ public final AtomicInteger threads = new AtomicInteger (1 );
278
+
279
+ private StoreAdapterThread (StoreAdapter storeAdapter ) {
280
+ this .storeAdapter = storeAdapter ;
249
281
}
282
+
250
283
}
284
+
251
285
}
0 commit comments