diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/CrossDCTestEnricher.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/CrossDCTestEnricher.java
index 68971e9..64963e8 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/CrossDCTestEnricher.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/CrossDCTestEnricher.java
@@ -31,7 +31,6 @@ import org.jboss.arquillian.core.spi.Validate;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.api.annotation.Observes;
import org.jboss.arquillian.test.spi.event.suite.After;
-import org.jboss.arquillian.test.spi.event.suite.AfterSuite;
import org.jboss.arquillian.test.spi.event.suite.Before;
import org.jboss.logging.Logger;
import static org.junit.Assert.assertThat;
@@ -44,7 +43,12 @@ import org.keycloak.testsuite.crossdc.DC;
import org.keycloak.testsuite.crossdc.ServerSetup;
import java.util.Collection;
import java.util.function.Consumer;
+import java.util.stream.Stream;
+import org.jboss.arquillian.container.spi.Container;
+import org.jboss.arquillian.container.spi.event.StopContainer;
import org.jboss.arquillian.container.spi.event.StopSuiteContainers;
+import org.jboss.arquillian.core.api.Event;
+import org.jboss.arquillian.test.spi.event.suite.AfterSuite;
/**
*
@@ -58,6 +62,9 @@ public class CrossDCTestEnricher {
@Inject
private static Instance<ContainerController> containerController;
+ @Inject
+ private Event<StopContainer> stopContainer;
+
private static final Map<ContainerInfo, Keycloak> backendAdminClients = new HashMap<>();
private static final Map<ContainerInfo, KeycloakTestingClient> backendTestingClients = new HashMap<>();
@@ -87,6 +94,28 @@ public class CrossDCTestEnricher {
ServerSetup cacheServers = annotation.cacheServers();
ServerSetup authServers = annotation.authServers();
+ // Stop auth servers that otherwise could be hang connecting to a cache server stopped next
+ switch (authServers) {
+ case ALL_NODES_IN_EVERY_DC:
+ break;
+ case FIRST_NODE_IN_EVERY_DC:
+ DC.validDcsStream().forEach((DC dc) -> stopAuthServerBackendNode(dc, 1));
+ break;
+
+ case FIRST_NODE_IN_FIRST_DC:
+ stopAuthServerBackendNode(DC.FIRST, 1);
+ forAllBackendNodesInDc(DC.SECOND, CrossDCTestEnricher::stopAuthServerBackendNode);
+ break;
+
+ case ALL_NODES_IN_FIRST_DC_FIRST_NODE_IN_SECOND_DC:
+ stopAuthServerBackendNode(DC.SECOND, 1);
+ break;
+
+ case ALL_NODES_IN_FIRST_DC_NO_NODES_IN_SECOND_DC:
+ forAllBackendNodesInDc(DC.SECOND, CrossDCTestEnricher::stopAuthServerBackendNode);
+ break;
+ }
+
switch (cacheServers) {
case ALL_NODES_IN_EVERY_DC:
case FIRST_NODE_IN_EVERY_DC: //the same as ALL_NODES_IN_EVERY_DC as there is only one cache server per DC
@@ -107,24 +136,19 @@ public class CrossDCTestEnricher {
break;
case FIRST_NODE_IN_EVERY_DC:
DC.validDcsStream().forEach((DC dc) -> startAuthServerBackendNode(dc, 0));
- DC.validDcsStream().forEach((DC dc) -> stopAuthServerBackendNode(dc, 1));
break;
case FIRST_NODE_IN_FIRST_DC:
startAuthServerBackendNode(DC.FIRST, 0);
- stopAuthServerBackendNode(DC.FIRST, 1);
- forAllBackendNodesInDc(DC.SECOND, CrossDCTestEnricher::stopAuthServerBackendNode);
break;
case ALL_NODES_IN_FIRST_DC_FIRST_NODE_IN_SECOND_DC:
forAllBackendNodesInDc(DC.FIRST, CrossDCTestEnricher::startAuthServerBackendNode);
startAuthServerBackendNode(DC.SECOND, 0);
- stopAuthServerBackendNode(DC.SECOND, 1);
break;
case ALL_NODES_IN_FIRST_DC_NO_NODES_IN_SECOND_DC:
forAllBackendNodesInDc(DC.FIRST, CrossDCTestEnricher::startAuthServerBackendNode);
- forAllBackendNodesInDc(DC.SECOND, CrossDCTestEnricher::stopAuthServerBackendNode);
break;
}
@@ -137,11 +161,30 @@ public class CrossDCTestEnricher {
restorePeriodicTasks();
}
+ public void afterSuite(@Observes(precedence = 4) AfterSuite event) {
+ if (!suiteContext.isAuthServerCrossDc()) return;
+
+ // Unfortunately, in AfterSuite, containerController context is already cleaned so stopAuthServerBackendNode()
+ // and stopCacheServer cannot be used. On the other hand, Arquillian by default does not guarantee that cache
+ // servers are terminated only after auth servers were, so the termination has to be done in this enricher.
+
+ forAllBackendNodesStream()
+ .map(ContainerInfo::getArquillianContainer)
+ .map(StopContainer::new)
+ .forEach(stopContainer::fire);
+
+ DC.validDcsStream()
+ .map(CrossDCTestEnricher::getCacheServer)
+ .map(ContainerInfo::getArquillianContainer)
+ .map(StopContainer::new)
+ .forEach(stopContainer::fire);
+ }
+
public void stopSuiteContainers(@Observes(precedence = 4) StopSuiteContainers event) {
if (!suiteContext.isAuthServerCrossDc()) return;
- DC.validDcsStream().forEach(CrossDCTestEnricher::stopCacheServer);
forAllBackendNodes(CrossDCTestEnricher::stopAuthServerBackendNode);
+ DC.validDcsStream().forEach(CrossDCTestEnricher::stopCacheServer);
}
private static void createRESTClientsForNode(ContainerInfo node) {
@@ -257,11 +300,15 @@ public class CrossDCTestEnricher {
}
public static void forAllBackendNodes(Consumer<ContainerInfo> functionOnContainerInfo) {
- suiteContext.getDcAuthServerBackendsInfo().stream()
- .flatMap(Collection::stream)
+ forAllBackendNodesStream()
.forEach(functionOnContainerInfo);
}
+ public static Stream<ContainerInfo> forAllBackendNodesStream() {
+ return suiteContext.getDcAuthServerBackendsInfo().stream()
+ .flatMap(Collection::stream);
+ }
+
public static void forAllBackendNodesInDc(DC dc, Consumer<ContainerInfo> functionOnContainerInfo) {
assertValidDc(dc);
suiteContext.getDcAuthServerBackendsInfo().get(dc.ordinal()).stream()