keycloak-aplcache
Changes
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AppServerTestEnricher.java 11(+6 -5)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java 7(+5 -2)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/h2/H2TestEnricher.java 40(+40 -0)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java 4(+3 -1)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java 8(+6 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractClusterTest.java 59(+59 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/TwoNodeClusterTest.java 131(+131 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/ContainersTest.java 34(+0 -34)
testsuite/integration-arquillian/tests/pom.xml 135(+133 -2)
Details
diff --git a/testsuite/integration-arquillian/servers/pom.xml b/testsuite/integration-arquillian/servers/pom.xml
index 070dfb6..a4a3c81 100644
--- a/testsuite/integration-arquillian/servers/pom.xml
+++ b/testsuite/integration-arquillian/servers/pom.xml
@@ -41,6 +41,14 @@
</modules>
</profile>
<profile>
+ <id>auth-server-wildfly-cluster</id>
+ <modules>
+ <module>wildfly</module>
+ <module>wildfly-balancer</module>
+ </modules>
+ </profile>
+
+ <profile>
<id>auth-server-eap7</id>
<modules>
<module>eap7</module>
diff --git a/testsuite/integration-arquillian/servers/wildfly/pom.xml b/testsuite/integration-arquillian/servers/wildfly/pom.xml
index a39738a..87f8674 100644
--- a/testsuite/integration-arquillian/servers/wildfly/pom.xml
+++ b/testsuite/integration-arquillian/servers/wildfly/pom.xml
@@ -1,20 +1,20 @@
<?xml version="1.0"?>
<!--
- ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
- ~ and other contributors as indicated by the @author tags.
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
+~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+~ and other contributors as indicated by the @author tags.
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~ http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
@@ -254,16 +254,16 @@
<goal>copy-resources</goal>
</goals>
<configuration>
- <outputDirectory>${keycloak.server.home}/standalone/configuration</outputDirectory>
- <resources>
- <resource>
- <directory>src/main/keystore</directory>
- <includes>
- <include>keycloak.jks</include>
- <include>keycloak.truststore</include>
- </includes>
- </resource>
- </resources>
+ <outputDirectory>${keycloak.server.home}/standalone/configuration</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/keystore</directory>
+ <includes>
+ <include>keycloak.jks</include>
+ <include>keycloak.truststore</include>
+ </includes>
+ </resource>
+ </resources>
</configuration>
</execution>
</executions>
@@ -412,5 +412,50 @@
</plugins>
</build>
</profile>
+
+ <profile>
+ <id>auth-server-wildfly-cluster</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>xml-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>configure-wildfly-datasource</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>transform</goal>
+ </goals>
+ <configuration>
+ <transformationSets>
+ <!-- point KeycloakDS datasource to H2 running on TCP port -->
+ <transformationSet>
+ <dir>${keycloak.server.home}/standalone/configuration</dir>
+ <includes>
+ <include>standalone-ha.xml</include>
+ </includes>
+ <stylesheet>src/main/xslt/datasource-jdbc-url.xsl</stylesheet>
+ <outputDir>${keycloak.server.home}/standalone/configuration</outputDir>
+ <parameters>
+ <parameter>
+ <name>pool.name</name>
+ <value>KeycloakDS</value>
+ </parameter>
+ <parameter>
+ <name>jdbc.url</name>
+ <value>jdbc:h2:tcp://${jboss.bind.address:localhost}:9092/mem:keycloak;DB_CLOSE_DELAY=-1</value>
+ </parameter>
+ </parameters>
+ </transformationSet>
+ </transformationSets>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+
</profiles>
</project>
diff --git a/testsuite/integration-arquillian/servers/wildfly/src/main/xslt/datasource-jdbc-url.xsl b/testsuite/integration-arquillian/servers/wildfly/src/main/xslt/datasource-jdbc-url.xsl
new file mode 100644
index 0000000..589ee4c
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/wildfly/src/main/xslt/datasource-jdbc-url.xsl
@@ -0,0 +1,36 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ xmlns:j="urn:jboss:domain:4.0"
+ xmlns:ds="urn:jboss:domain:datasources:4.0"
+ xmlns:k="urn:jboss:domain:keycloak:1.1"
+ xmlns:sec="urn:jboss:domain:security:1.2"
+ version="2.0"
+ exclude-result-prefixes="xalan j ds k sec">
+
+ <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" xalan:indent-amount="4" standalone="no"/>
+ <xsl:strip-space elements="*"/>
+
+
+ <xsl:variable name="nsDS" select="'urn:jboss:domain:datasources:'"/>
+
+ <xsl:param name="pool.name" select="'KeycloakDS'"/>
+ <xsl:param name="jdbc.url" />
+
+ <!-- replace JDBC URL -->
+ <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $nsDS)]
+ /*[local-name()='datasources' and starts-with(namespace-uri(), $nsDS)]
+ /*[local-name()='datasource' and starts-with(namespace-uri(), $nsDS) and @pool-name=$pool.name]
+ /*[local-name()='connection-url' and starts-with(namespace-uri(), $nsDS)]">
+ <connection-url>
+ <xsl:value-of select="$jdbc.url"/>
+ </connection-url>
+ </xsl:template>
+
+ <!-- Copy everything else. -->
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()" />
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/servers/wildfly-balancer/assembly.xml b/testsuite/integration-arquillian/servers/wildfly-balancer/assembly.xml
new file mode 100644
index 0000000..a3e36ae
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/wildfly-balancer/assembly.xml
@@ -0,0 +1,46 @@
+<!--
+ ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+ ~ and other contributors as indicated by the @author tags.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<assembly>
+
+ <id>wildfly-balancer</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>${wildfly.balancer.home}</directory>
+ <outputDirectory>wildfly-balancer-${project.version}</outputDirectory>
+ <excludes>
+ <exclude>**/*.sh</exclude>
+ </excludes>
+ </fileSet>
+ <fileSet>
+ <directory>${wildfly.balancer.home}</directory>
+ <outputDirectory>wildfly-balancer-${project.version}</outputDirectory>
+ <includes>
+ <include>**/*.sh</include>
+ </includes>
+ <fileMode>0755</fileMode>
+ </fileSet>
+ </fileSets>
+
+</assembly>
diff --git a/testsuite/integration-arquillian/servers/wildfly-balancer/pom.xml b/testsuite/integration-arquillian/servers/wildfly-balancer/pom.xml
new file mode 100644
index 0000000..895be72
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/wildfly-balancer/pom.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0"?>
+<!--
+~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+~ and other contributors as indicated by the @author tags.
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~ http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
+
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <parent>
+ <groupId>org.keycloak.testsuite</groupId>
+ <artifactId>integration-arquillian-servers</artifactId>
+ <version>1.9.0.Final-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>integration-arquillian-server-wildfly-balancer</artifactId>
+ <packaging>pom</packaging>
+ <name>Wildfly Load Balancer</name>
+
+ <properties>
+ <wildfly.balancer.home>${project.build.directory}/unpacked/wildfly-${wildfly.version}</wildfly.balancer.home>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-wildfly</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.wildfly</groupId>
+ <artifactId>wildfly-dist</artifactId>
+ <version>${wildfly.version}</version>
+ <type>zip</type>
+ <outputDirectory>${project.build.directory}/unpacked</outputDirectory>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>xml-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>configure-mod-cluster</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>transform</goal>
+ </goals>
+ <configuration>
+ <transformationSets>
+ <transformationSet>
+ <dir>${wildfly.balancer.home}/standalone/configuration</dir>
+ <includes>
+ <include>standalone.xml</include>
+ </includes>
+ <stylesheet>src/main/xslt/mod_cluster.xsl</stylesheet>
+ <outputDir>${wildfly.balancer.home}/standalone/configuration</outputDir>
+ </transformationSet>
+ </transformationSets>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>create-zip</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptors>
+ <descriptor>assembly.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/testsuite/integration-arquillian/servers/wildfly-balancer/src/main/xslt/mod_cluster.xsl b/testsuite/integration-arquillian/servers/wildfly-balancer/src/main/xslt/mod_cluster.xsl
new file mode 100644
index 0000000..9cb3774
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/wildfly-balancer/src/main/xslt/mod_cluster.xsl
@@ -0,0 +1,73 @@
+<!--
+~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+~ and other contributors as indicated by the @author tags.
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~ http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ xmlns:s="urn:jboss:domain:4.0"
+ xmlns:u="urn:jboss:domain:undertow:3.0"
+ version="2.0"
+ exclude-result-prefixes="xalan j u">
+
+ <xsl:param name="config"/>
+
+ <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" xalan:indent-amount="4" standalone="no"/>
+ <xsl:strip-space elements="*"/>
+
+ <!--enable mod_cluster extension-->
+ <xsl:template match="//s:extensions">
+ <xsl:copy>
+ <xsl:apply-templates select="node()|@*"/>
+ <extension module="org.jboss.as.modcluster"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!--add filter-ref-->
+ <xsl:template match="//u:server[@name='default-server']/u:host[@name='default-host']">
+ <xsl:copy>
+ <xsl:apply-templates select="node()|@*"/>
+ <filter-ref name="modcluster"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!--add filter-->
+ <xsl:template match="//u:filters">
+ <xsl:copy>
+ <xsl:apply-templates select="node()|@*"/>
+ <mod-cluster
+ name="modcluster"
+ advertise-socket-binding="modcluster"
+ management-socket-binding="http"
+ enable-http2="true"
+ />
+ </xsl:copy>
+ </xsl:template>
+
+ <!--add socket binding-->
+ <xsl:template match="//s:socket-binding-group[@name='standard-sockets']">
+ <xsl:copy>
+ <xsl:apply-templates select="node()|@*"/>
+ <socket-binding name="modcluster" port="23364" multicast-address="224.0.1.105"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()" />
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/pom.xml b/testsuite/integration-arquillian/tests/base/pom.xml
index e08b2ad..cc84be1 100644
--- a/testsuite/integration-arquillian/tests/base/pom.xml
+++ b/testsuite/integration-arquillian/tests/base/pom.xml
@@ -35,7 +35,10 @@
<exclude.console>-</exclude.console>
<exclude.account>-</exclude.account>
<exclude.client>-</exclude.client>
- <exclude.migration>-</exclude.migration>
+ <!--exclude migration tests by default, enabled by 'migration' profile in tests/pom.xml-->
+ <exclude.migration>**/migration/**/*Test.java</exclude.migration>
+ <!--exclude cluster tests by default, enabled by 'auth-server-*-cluster' profiles in tests/pom.xml-->
+ <exclude.cluster>**/cluster/**/*Test.java</exclude.cluster>
</properties>
<dependencies>
@@ -75,6 +78,7 @@
<exclude>${exclude.account}</exclude>
<exclude>${exclude.client}</exclude>
<exclude>${exclude.migration}</exclude>
+ <exclude>${exclude.cluster}</exclude>
</excludes>
</configuration>
</plugin>
@@ -108,29 +112,4 @@
</build>
- <profiles>
- <profile>
- <id>no-account</id>
- <properties>
- <!-- Exclude all account management tests. -->
- <exclude.account>**/account/**/*Test.java</exclude.account>
- </properties>
- </profile>
- <profile>
- <id>no-client</id>
- <properties>
- <!-- Exclude all client tests. -->
- <exclude.client>**/client/**/*Test.java</exclude.client>
- </properties>
- </profile>
- <profile>
- <id>adapters-only</id>
- <properties>
- <exclude.account>**/account/**/*Test.java</exclude.account>
- <exclude.client>**/client/**/*Test.java</exclude.client>
- <exclude.migration>**/migration/**/*Test.java</exclude.migration>
- </properties>
- </profile>
- </profiles>
-
</project>
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 9289593..e8703b4 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 5000e3b..9cbfce6 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/h2/H2TestEnricher.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/h2/H2TestEnricher.java
new file mode 100644
index 0000000..705cbad
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/h2/H2TestEnricher.java
@@ -0,0 +1,40 @@
+package org.keycloak.testsuite.arquillian.h2;
+
+import java.sql.SQLException;
+import org.jboss.arquillian.core.api.annotation.Observes;
+import org.jboss.arquillian.test.spi.event.suite.AfterSuite;
+import org.jboss.arquillian.test.spi.event.suite.BeforeSuite;
+import org.jboss.logging.Logger;
+import org.h2.tools.Server;
+
+/**
+ * Starts H2 before suite and stops it after.
+ *
+ * @author tkyjovsk
+ */
+public class H2TestEnricher {
+
+ protected final Logger log = Logger.getLogger(this.getClass());
+
+ boolean runH2 = Boolean.parseBoolean(System.getProperty("run.h2", "false"));
+
+ private Server server = null;
+
+ public void startH2(@Observes(precedence = 2) BeforeSuite event) throws SQLException {
+ if (runH2) {
+ log.info("Starting H2 database.");
+ server = Server.createTcpServer();
+ server.start();
+ log.info(String.format("URL: %s", server.getURL()));
+ }
+ }
+
+ public void stopH2(@Observes(precedence = -2) AfterSuite event) {
+ if (runH2 && server.isRunning(false)) {
+ log.info("Stopping H2 database.");
+ server.stop();
+ assert !server.isRunning(false);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java
index 7154b8a..275974f 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java
@@ -26,6 +26,7 @@ import org.jboss.arquillian.core.spi.LoadableExtension;
import org.jboss.arquillian.graphene.location.CustomizableURLResourceProvider;
import org.jboss.arquillian.test.spi.enricher.resource.ResourceProvider;
import org.jboss.arquillian.test.spi.execution.TestExecutionDecider;
+import org.keycloak.testsuite.arquillian.h2.H2TestEnricher;
import org.keycloak.testsuite.arquillian.migration.MigrationTestExecutionDecider;
import org.keycloak.testsuite.arquillian.undertow.CustomUndertowContainer;
@@ -48,7 +49,8 @@ public class KeycloakArquillianExtension implements LoadableExtension {
.service(DeploymentScenarioGenerator.class, DeploymentTargetModifier.class)
.service(ApplicationArchiveProcessor.class, DeploymentArchiveProcessor.class)
.observer(AuthServerTestEnricher.class)
- .observer(AppServerTestEnricher.class);
+ .observer(AppServerTestEnricher.class)
+ .observer(H2TestEnricher.class);
builder
.service(DeployableContainer.class, CustomUndertowContainer.class);
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 c4bd23b..929c23d 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/cluster/AbstractClusterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cluster/AbstractClusterTest.java
new file mode 100644
index 0000000..9dd6089
--- /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<Keycloak> 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 0000000..0984124
--- /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<RealmRepresentation> 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 6c13daa..404f5b5 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
@@ -71,7 +71,7 @@
<configuration>
<property name="enabled">${auth.server.wildfly.cluster}</property>
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
- <property name="jbossHome">${wildfly.home}</property>
+ <property name="jbossHome">${keycloak.balancer.home}</property>
<property name="javaVmArguments">
-Djboss.socket.binding.port-offset=${auth.server.port.offset}
-Xms64m -Xmx512m -XX:MaxPermSize=256m
@@ -86,15 +86,35 @@
<property name="enabled">${auth.server.wildfly.cluster}</property>
<property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
<property name="jbossHome">${keycloak.backend1.home}</property>
+ <property name="serverConfig">standalone-ha.xml</property>
<property name="javaVmArguments">
-Djboss.socket.binding.port-offset=${auth.server.backend1.port.offset}
-Xms64m -Xmx512m -XX:MaxPermSize=256m
${adapter.test.props}
+ -Djboss.node.name=node1
</property>
+ <!--<property name="outputToConsole">false</property>-->
<property name="managementPort">${auth.server.backend1.management.port}</property>
<property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
</configuration>
</container>
+ <container qualifier="auth-server-wildfly-backend2" mode="manual" >
+ <configuration>
+ <property name="enabled">${auth.server.wildfly.cluster}</property>
+ <property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
+ <property name="jbossHome">${keycloak.backend2.home}</property>
+ <property name="serverConfig">standalone-ha.xml</property>
+ <property name="javaVmArguments">
+ -Djboss.socket.binding.port-offset=${auth.server.backend2.port.offset}
+ -Xms64m -Xmx512m -XX:MaxPermSize=256m
+ ${adapter.test.props}
+ -Djboss.node.name=node2
+ </property>
+ <!--<property name="outputToConsole">false</property>-->
+ <property name="managementPort">${auth.server.backend2.management.port}</property>
+ <property name="startupTimeoutInSeconds">${startup.timeout.sec}</property>
+ </configuration>
+ </container>
</group>
<container qualifier="auth-server-eap7" mode="suite" >
testsuite/integration-arquillian/tests/pom.xml 135(+133 -2)
diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml
index 06511a2..4e35234 100644
--- a/testsuite/integration-arquillian/tests/pom.xml
+++ b/testsuite/integration-arquillian/tests/pom.xml
@@ -159,7 +159,27 @@
</build>
<profiles>
-
+
+ <profile>
+ <id>no-account</id>
+ <properties>
+ <exclude.account>**/account/**/*Test.java</exclude.account>
+ </properties>
+ </profile>
+ <profile>
+ <id>no-client</id>
+ <properties>
+ <exclude.client>**/client/**/*Test.java</exclude.client>
+ </properties>
+ </profile>
+ <profile>
+ <id>no-base</id>
+ <properties>
+ <exclude.account>**/account/**/*Test.java</exclude.account>
+ <exclude.client>**/client/**/*Test.java</exclude.client>
+ </properties>
+ </profile>
+
<profile>
<id>common-test-dependencies</id>
<activation>
@@ -348,6 +368,7 @@
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
@@ -398,6 +419,7 @@
<adapter.test.props/>
<keycloak.home>${containers.home}/keycloak-${project.version}</keycloak.home>
<jboss.server.config.dir>${keycloak.home}/standalone/configuration</jboss.server.config.dir>
+ <h2.version>1.3.173</h2.version>
</properties>
<dependencies>
<dependency>
@@ -450,6 +472,111 @@
</build>
</profile>
+
+ <profile>
+ <id>auth-server-wildfly-cluster</id>
+ <properties>
+ <!--disable exclusion pattern for cluster test which is enabled by default in base/pom.xml-->
+ <exclude.cluster>-</exclude.cluster>
+
+ <auth.server.container>auth-server-wildfly-cluster</auth.server.container>
+ <startup.timeout.sec>300</startup.timeout.sec>
+ <adapter.test.props/>
+ <h2.version>1.3.173</h2.version>
+
+ <keycloak.balancer.home>${containers.home}/balancer/wildfly-balancer-${project.version}</keycloak.balancer.home>
+ <keycloak.backend1.home>${containers.home}/node1/keycloak-${project.version}</keycloak.backend1.home>
+ <keycloak.backend2.home>${containers.home}/node2/keycloak-${project.version}</keycloak.backend2.home>
+
+ <keycloak.home>${keycloak.backend1.home}</keycloak.home>
+ <jboss.server.config.dir>${keycloak.home}/standalone/configuration</jboss.server.config.dir>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.wildfly</groupId>
+ <artifactId>wildfly-arquillian-container-managed</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <run.h2>true</run.h2>
+
+ <auth.server.wildfly.cluster>true</auth.server.wildfly.cluster>
+ <auth.server.undertow>false</auth.server.undertow>
+ <adapter.test.props>${adapter.test.props}</adapter.test.props>
+
+ <keycloak.balancer.home>${keycloak.balancer.home}</keycloak.balancer.home>
+ <keycloak.backend1.home>${keycloak.backend1.home}</keycloak.backend1.home>
+ <keycloak.backend2.home>${keycloak.backend2.home}</keycloak.backend2.home>
+
+ <!--100-->
+ <auth.server.backend1.port.offset>101</auth.server.backend1.port.offset>
+ <auth.server.backend2.port.offset>102</auth.server.backend2.port.offset>
+ <!--8180-->
+ <auth.server.backend1.http.port>8181</auth.server.backend1.http.port>
+ <auth.server.backend2.http.port>8182</auth.server.backend2.http.port>
+ <!--8543-->
+ <auth.server.backend1.https.port>8544</auth.server.backend1.https.port>
+ <auth.server.backend2.https.port>8545</auth.server.backend2.https.port>
+ <!--10090-->
+ <auth.server.backend1.management.port>10091</auth.server.backend1.management.port>
+ <auth.server.backend2.management.port>10092</auth.server.backend2.management.port>
+ <!--10099-->
+ <auth.server.backend1.management.port.jmx>10100</auth.server.backend1.management.port.jmx>
+ <auth.server.backend2.management.port.jmx>10101</auth.server.backend2.management.port.jmx>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack-auth-server-wildfly</id>
+ <phase>generate-test-resources</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.keycloak.testsuite</groupId>
+ <artifactId>integration-arquillian-server-wildfly-balancer</artifactId>
+ <version>${project.version}</version>
+ <type>zip</type>
+ <outputDirectory>${containers.home}/balancer</outputDirectory>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.keycloak.testsuite</groupId>
+ <artifactId>integration-arquillian-server-wildfly</artifactId>
+ <version>${project.version}</version>
+ <type>zip</type>
+ <outputDirectory>${containers.home}/node1</outputDirectory>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.keycloak.testsuite</groupId>
+ <artifactId>integration-arquillian-server-wildfly</artifactId>
+ <version>${project.version}</version>
+ <type>zip</type>
+ <outputDirectory>${containers.home}/node2</outputDirectory>
+ </artifactItem>
+ </artifactItems>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ </profile>
+
<profile>
<id>auth-server-eap7</id>
<properties>
@@ -538,6 +665,10 @@
<name>migrated.auth.server.version</name>
</property>
</activation>
+ <properties>
+ <!--diable exclusion pattern for migration tests, which is enabled by default in the base/pom.xml-->
+ <exclude.migration>-</exclude.migration>
+ </properties>
<build>
<plugins>
<plugin>
@@ -743,7 +874,7 @@
</pluginManagement>
</build>
</profile>
-
+
</profiles>
</project>