diff --git a/testsuite/integration-arquillian/tests/base/pom.xml b/testsuite/integration-arquillian/tests/base/pom.xml index e08b2ade8b..a0e7f09c95 100644 --- a/testsuite/integration-arquillian/tests/base/pom.xml +++ b/testsuite/integration-arquillian/tests/base/pom.xml @@ -35,7 +35,10 @@ - - - - - + + **/migration/**/*Test.java + + **/cluster/**/*Test.java @@ -108,29 +111,4 @@ - - - no-account - - - **/account/**/*Test.java - - - - no-client - - - **/client/**/*Test.java - - - - adapters-only - - **/account/**/*Test.java - **/client/**/*Test.java - **/migration/**/*Test.java - - - - diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AppServerTestEnricher.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AppServerTestEnricher.java index 9289593232..e8703b450d 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AppServerTestEnricher.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AppServerTestEnricher.java @@ -40,9 +40,10 @@ public class AppServerTestEnricher { String appServerQ = (annotatedClass == null ? null : annotatedClass.getAnnotation(AppServerContainer.class).value()); - return appServerQ == null || appServerQ.isEmpty() - ? getAuthServerQualifier() // app server == auth server - : appServerQ; + return annotatedClass == null ? null // no @AppServerContainer annotation --> no adapter test + : (appServerQ == null || appServerQ.isEmpty() // @AppServerContainer annotation present but qualifier not set --> relative adapter test + ? getAuthServerQualifier() // app server == auth server + : appServerQ); } public static String getAppServerContextRoot() { @@ -129,7 +130,7 @@ public class AppServerTestEnricher { String jbossHomePath = appServerInfo.getProperties().get("jbossHome"); File bin = new File(jbossHomePath + "/bin"); - + File clientJar = new File(jbossHomePath + "/bin/client/jboss-cli-client.jar"); if (!clientJar.exists()) { clientJar = new File(jbossHomePath + "/bin/client/jboss-client.jar"); // AS7 @@ -137,7 +138,7 @@ public class AppServerTestEnricher { if (!clientJar.exists()) { throw new IOException("JBoss CLI client JAR not found."); } - + String command = "java -jar " + clientJar.getAbsolutePath(); String adapterScript = "adapter-install.cli"; String samlAdapterScript = "adapter-install-saml.cli"; diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java index 5000e3b482..9cbfce6e6a 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java @@ -110,7 +110,10 @@ public class AuthServerTestEnricher { boolean authServerCluster = authServerQualifier.endsWith("-cluster"); - String authServerType = authServerQualifier.replaceAll("^auth-server-", "").replaceAll("-cluster$", ""); + String authServerType = authServerQualifier.replaceAll("auth-server-", "").replaceAll("-cluster", ""); + + log.info("authServerType:" + authServerType); + String authServerFrontend = authServerCluster ? "auth-server-" + authServerType + "-balancer" // in cluster mode the load-balancer container serves as auth server frontend : authServerQualifier; // single-node mode @@ -133,7 +136,7 @@ public class AuthServerTestEnricher { if (suiteContext.getAuthServerInfo() == null) { throw new RuntimeException(String.format("No auth server activated. A container matching '%s' needs to be enabled in arquillian.xml.", authServerFrontend)); } - if (authServerCluster && !suiteContext.getAuthServerBackendsInfo().isEmpty()) { + if (authServerCluster && suiteContext.getAuthServerBackendsInfo().isEmpty()) { throw new RuntimeException(String.format("No cluster backend nodes activated. Containers matching '%sN' need to be enabled in arquillian.xml.", authServerBackend)); } diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java index c4bd23b45a..929c23d2b7 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java @@ -93,9 +93,13 @@ public final class SuiteContext { @Override public String toString() { + String containers = "Auth server: " + (isAuthServerCluster() ? "\nFrontend: " : "") + + authServerInfo.getQualifier() + "\n"; + for (ContainerInfo bInfo : getAuthServerBackendsInfo()) { + containers += "Backend: " + bInfo + "\n"; + } return "SUITE CONTEXT:\n" - + "Auth server: " + authServerInfo.getQualifier() + "\n" - +(isAuthServerCluster() ? "Auth server cluster: " + getAuthServerBackendsInfo().size() + " nodes+\n" : ""); + + containers; } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/ContainersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/ContainersTest.java deleted file mode 100644 index 27053aef54..0000000000 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/ContainersTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.keycloak.testsuite; - -import java.util.List; -import org.jboss.arquillian.container.test.api.ContainerController; -import org.jboss.arquillian.test.api.ArquillianResource; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import org.junit.Test; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.testsuite.arquillian.AuthServerTestEnricher; - -/** - * - * @author tkyjovsk - */ -public class ContainersTest extends AbstractKeycloakTest { - - @ArquillianResource - ContainerController controller; - - @Override - public void addTestRealms(List testRealms) { - } - - - @Test - public void testAuthServer() { - - log.info("AUTH SERVER should be started."); - assertTrue(controller.isStarted(AuthServerTestEnricher.getAuthServerQualifier())); - - } - -} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractClusterTest.java new file mode 100644 index 0000000000..9dd6089e06 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractClusterTest.java @@ -0,0 +1,59 @@ +package org.keycloak.testsuite.cluster; + +import java.util.ArrayList; +import java.util.List; +import org.jboss.arquillian.container.test.api.ContainerController; +import org.jboss.arquillian.test.api.ArquillianResource; +import static org.junit.Assert.assertTrue; +import org.keycloak.admin.client.Keycloak; +import org.keycloak.models.Constants; +import org.keycloak.testsuite.AbstractKeycloakTest; +import org.keycloak.testsuite.arquillian.ContainerInfo; +import static org.keycloak.testsuite.auth.page.AuthRealm.ADMIN; +import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER; + +/** + * + * @author tkyjovsk + */ +public abstract class AbstractClusterTest extends AbstractKeycloakTest { + + @ArquillianResource + protected ContainerController controller; + + protected List backendAdminClients = new ArrayList<>(); + + public void startBackendNodes(int count) { + if (count < 0 || count > 10) { + throw new IllegalArgumentException(); + } + assertTrue(suiteContext.getAuthServerBackendsInfo().size() >= count); + for (int i = 0; i < count; i++) { + + ContainerInfo backendNode = suiteContext.getAuthServerBackendsInfo().get(i); + + controller.start(backendNode.getQualifier()); + assertTrue(controller.isStarted(backendNode.getQualifier())); + + log.info("Initializing admin client for: '" + backendNode.getContextRoot() + "/auth'"); + backendAdminClients.add(Keycloak.getInstance(backendNode.getContextRoot() + "/auth", + MASTER, ADMIN, ADMIN, Constants.ADMIN_CLI_CLIENT_ID)); + } + } + + protected ContainerInfo backendInfo(int i) { + return suiteContext.getAuthServerBackendsInfo().get(i); + } + + protected void startBackendNode(int i) { + String container = backendInfo(i).getQualifier(); + if (!controller.isStarted(container)) { + controller.start(container); + } + } + + protected void stopBackendNode(int i) { + controller.kill(backendInfo(i).getQualifier()); + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/TwoNodeClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/TwoNodeClusterTest.java new file mode 100644 index 0000000000..0984124c0a --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/TwoNodeClusterTest.java @@ -0,0 +1,131 @@ +package org.keycloak.testsuite.cluster; + +import java.util.List; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import org.junit.Before; +import org.junit.Test; +import org.keycloak.admin.client.Keycloak; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.arquillian.ContainerInfo; +import static org.keycloak.testsuite.auth.page.AuthRealm.TEST; +import static org.keycloak.testsuite.util.WaitUtils.pause; + +/** + * + * @author tkyjovsk + */ +public class TwoNodeClusterTest extends AbstractClusterTest { + + @Override + public void addTestRealms(List testRealms) { + } + + @Before + public void beforeTwoNodeClusterTest() { + startBackendNodes(2); + pause(3000); + } + + @Test + public void testRealm() { + testRealm(TEST, false); + } + + @Test + public void testRealmWithFailover() { + testRealm(TEST + "_fo", true); + } + + public void testRealm(String realm, boolean containerFailover) { + RealmRepresentation testRealm = new RealmRepresentation(); + testRealm.setRealm(realm); + testRealm.setEnabled(true); + + // CREATE on node1 + log.info("Creating test realm via node1."); + backend1AdminClient().realms().create(testRealm); + log.info("Test realm created."); + + // check if created on node1 + RealmRepresentation testRealmOnBackend1 = backend1AdminClient().realms().realm(realm).toRepresentation(); + assertEquals(testRealmOnBackend1.getRealm(), testRealm.getRealm()); + if (containerFailover) { + stopBackend1(); + } + + // check if created on node2 + RealmRepresentation testRealmOnBackend2 = backend2AdminClient().realms().realm(realm).toRepresentation(); + assertEquals(testRealmOnBackend1.getId(), testRealmOnBackend2.getId()); + assertEquals(testRealmOnBackend1.getRealm(), testRealmOnBackend2.getRealm()); + + failback(); + + // UPDATE on node2 + testRealmOnBackend2.setRealm(realm + "_updated"); + backend2AdminClient().realms().realm(realm).update(testRealmOnBackend2); + if (containerFailover) { + stopBackend2(); + } + // check if updated on node1 + testRealmOnBackend1 = backend1AdminClient().realms().realm(realm).toRepresentation(); + assertEquals(testRealmOnBackend1.getId(), testRealmOnBackend2.getId()); + assertEquals(testRealmOnBackend1.getRealm(), testRealmOnBackend2.getRealm()); + + failback(); + + // DELETE on node1 + backend1AdminClient().realms().realm(realm).remove(); + if (containerFailover) { + stopBackend1(); + } + // check if deleted on node2 + boolean testRealmOnBackend2Exists = false; + for (RealmRepresentation realmOnBackend2 : backend2AdminClient().realms().findAll()) { + if (realm.equals(realmOnBackend2.getRealm()) + || testRealmOnBackend1.getId().equals(realmOnBackend2.getId())) { + testRealmOnBackend2Exists = true; + break; + } + } + assertFalse(testRealmOnBackend2Exists); + } + + protected ContainerInfo backend1Info() { + return backendInfo(0); + } + + protected ContainerInfo backend2Info() { + return backendInfo(1); + } + + protected Keycloak backend1AdminClient() { + return backendAdminClients.get(0); + } + + protected Keycloak backend2AdminClient() { + return backendAdminClients.get(1); + } + + protected void startBackend1() { + startBackendNode(0); + } + + protected void startBackend2() { + startBackendNode(1); + } + + protected void failback() { + startBackend1(); + startBackend2(); + } + + protected void stopBackend1() { + stopBackendNode(0); + } + + protected void stopBackend2() { + stopBackendNode(1); + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml index 9ad14da3a7..404f5b5fe3 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml @@ -86,11 +86,14 @@ ${auth.server.wildfly.cluster} org.jboss.as.arquillian.container.managed.ManagedDeployableContainer ${keycloak.backend1.home} + standalone-ha.xml -Djboss.socket.binding.port-offset=${auth.server.backend1.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m ${adapter.test.props} + -Djboss.node.name=node1 + ${auth.server.backend1.management.port} ${startup.timeout.sec} @@ -100,11 +103,14 @@ ${auth.server.wildfly.cluster} org.jboss.as.arquillian.container.managed.ManagedDeployableContainer ${keycloak.backend2.home} + standalone-ha.xml -Djboss.socket.binding.port-offset=${auth.server.backend2.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m ${adapter.test.props} + -Djboss.node.name=node2 + ${auth.server.backend2.management.port} ${startup.timeout.sec} diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml index 715cadbe03..4e35234120 100644 --- a/testsuite/integration-arquillian/tests/pom.xml +++ b/testsuite/integration-arquillian/tests/pom.xml @@ -159,7 +159,27 @@ - + + + no-account + + **/account/**/*Test.java + + + + no-client + + **/client/**/*Test.java + + + + no-base + + **/account/**/*Test.java + **/client/**/*Test.java + + + common-test-dependencies @@ -456,12 +476,15 @@ auth-server-wildfly-cluster + + - + auth-server-wildfly-cluster 300 1.3.173 - ${containers.home}/balancer/wildfly-${project.version} + ${containers.home}/balancer/wildfly-balancer-${project.version} ${containers.home}/node1/keycloak-${project.version} ${containers.home}/node2/keycloak-${project.version} @@ -482,6 +505,8 @@ maven-surefire-plugin + true + true false ${adapter.test.props} @@ -495,7 +520,7 @@ 102 8181 - 8181 + 8182 8544 8545 @@ -522,19 +547,24 @@ org.keycloak.testsuite - integration-arquillian-server-wildfly + integration-arquillian-server-wildfly-balancer ${project.version} zip - balancer - ${containers.home} + ${containers.home}/balancer org.keycloak.testsuite integration-arquillian-server-wildfly ${project.version} zip - backend - ${containers.home} + ${containers.home}/node1 + + + org.keycloak.testsuite + integration-arquillian-server-wildfly + ${project.version} + zip + ${containers.home}/node2 true @@ -635,6 +665,10 @@ migrated.auth.server.version + + + - + @@ -840,7 +874,7 @@ - +