diff --git a/pom.xml b/pom.xml index c334bfa624..35b1a3cff0 100644 --- a/pom.xml +++ b/pom.xml @@ -1464,6 +1464,11 @@ keycloak-quarkus-server-app ${project.version} + + org.keycloak + keycloak-junit5 + ${project.version} + org.keycloak keycloak-admin-ui diff --git a/quarkus/tests/integration/pom.xml b/quarkus/tests/integration/pom.xml index fa67a6fd78..510ed03181 100644 --- a/quarkus/tests/integration/pom.xml +++ b/quarkus/tests/integration/pom.xml @@ -41,7 +41,37 @@ org.keycloak - keycloak-quarkus-server + keycloak-junit5 + test + + + io.rest-assured + rest-assured + test + + + com.approvaltests + approvaltests + ${approvaltests.version} + test + + + org.bouncycastle + bc-fips + ${bouncycastle.fips.version} + test + + + org.bouncycastle + bcpkix-fips + ${bouncycastle.pkixfips.version} + test + + + org.bouncycastle + bctls-fips + ${bouncycastle.tlsfips.version} + test @@ -58,58 +88,6 @@ - - io.quarkus - quarkus-junit5-internal - - - junit - junit - ${junit.version} - compile - - - org.keycloak - keycloak-quarkus-dist - zip - - - io.quarkus - quarkus-junit5 - - - io.rest-assured - rest-assured - - - org.testcontainers - junit-jupiter - - - com.approvaltests - approvaltests - ${approvaltests.version} - - - org.testcontainers - postgresql - - - org.testcontainers - cockroachdb - - - org.testcontainers - mariadb - - - org.testcontainers - mysql - - - org.apache.maven.wagon - wagon-http-shared - diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/approvalTests/KcNamerFactory.java b/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/approvalTests/KcNamerFactory.java deleted file mode 100644 index 464f1aeb88..0000000000 --- a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/approvalTests/KcNamerFactory.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.keycloak.it.junit5.extension.approvalTests; - -import org.approvaltests.namer.NamedEnvironment; -import org.approvaltests.namer.NamerFactory; - -public class KcNamerFactory extends NamerFactory { - - public static NamedEnvironment asWindowsOsSpecificTest() - { - return asMachineSpecificTest(new WindowsOrUnixOsEnvironmentLabeller()); - } -} diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/approvalTests/WindowsOrUnixOsEnvironmentLabeller.java b/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/approvalTests/WindowsOrUnixOsEnvironmentLabeller.java deleted file mode 100644 index 4f258823f4..0000000000 --- a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/approvalTests/WindowsOrUnixOsEnvironmentLabeller.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.keycloak.it.junit5.extension.approvalTests; - -import org.lambda.functions.Function0; - -import java.util.Locale; - -public class WindowsOrUnixOsEnvironmentLabeller implements Function0 { - - private static final String WINDOWS_NAME = "windows"; - private static final String UNIX_NAME = "unix"; - - @Override - public String call() - { - String osName = System.getProperty("os.name"); - - if(osName.toLowerCase(Locale.ROOT).contains(WINDOWS_NAME)) { - return WINDOWS_NAME; - } - - //unix suffices, as basically all other OSses use sh files - return UNIX_NAME; - } -} diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/Maven.java b/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/Maven.java deleted file mode 100644 index 8d34e71a09..0000000000 --- a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/Maven.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2022 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. - */ - -package org.keycloak.it.utils; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import org.eclipse.aether.RepositorySystem; -import org.eclipse.aether.artifact.Artifact; -import org.eclipse.aether.artifact.DefaultArtifact; -import org.eclipse.aether.repository.RemoteRepository; -import org.eclipse.aether.resolution.ArtifactDescriptorRequest; -import org.eclipse.aether.resolution.ArtifactDescriptorResult; -import org.eclipse.aether.resolution.ArtifactRequest; - -import io.quarkus.bootstrap.resolver.maven.BootstrapMavenContext; -import io.quarkus.bootstrap.resolver.maven.workspace.LocalProject; -import io.quarkus.bootstrap.utils.BuildToolHelper; - -public final class Maven { - - public static Path resolveArtifact(String groupId, String artifactId) { - try { - Path projectDir = BuildToolHelper.getProjectDir(Paths.get(Maven.class.getResource(".").toURI())); - BootstrapMavenContext ctx = new BootstrapMavenContext( - BootstrapMavenContext.config().setPreferPomsFromWorkspace(true).setWorkspaceModuleParentHierarchy(true) - .setCurrentProject(projectDir.toString())); - LocalProject project = ctx.getCurrentProject(); - RepositorySystem repositorySystem = ctx.getRepositorySystem(); - List remoteRepositories = ctx.getRemoteRepositories(); - ArtifactDescriptorResult descrResult = repositorySystem.readArtifactDescriptor( - ctx.getRepositorySystemSession(), - new ArtifactDescriptorRequest() - .setArtifact(new DefaultArtifact(project.getGroupId(), project.getArtifactId(), "pom", project.getVersion())) - .setRepositories(remoteRepositories)); - - for (org.eclipse.aether.graph.Dependency dependency : descrResult.getManagedDependencies()) { - Artifact artifact = dependency.getArtifact(); - - if (artifact.getGroupId().equals(groupId) && artifact.getArtifactId().equals(artifactId)) { - return repositorySystem.resolveArtifact( - ctx.getRepositorySystemSession(), - new ArtifactRequest().setArtifact(artifact) - .setRepositories(remoteRepositories)) - .getArtifact().getFile().toPath(); - } - } - } catch (Exception cause) { - throw new RuntimeException("Failed to resolve artifact", cause); - } - - return null; - } -} diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/approvaltests/KcNamerFactory.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/approvaltests/KcNamerFactory.java new file mode 100644 index 0000000000..045a0c7997 --- /dev/null +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/approvaltests/KcNamerFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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. + */ + +package org.keycloak.it.approvaltests; + +import org.approvaltests.namer.NamedEnvironment; +import org.approvaltests.namer.NamerFactory; + +public class KcNamerFactory extends NamerFactory { + + public static NamedEnvironment asWindowsOsSpecificTest() + { + return asMachineSpecificTest(new WindowsOrUnixOsEnvironmentLabeller()); + } +} diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/approvaltests/WindowsOrUnixOsEnvironmentLabeller.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/approvaltests/WindowsOrUnixOsEnvironmentLabeller.java new file mode 100644 index 0000000000..391566eee9 --- /dev/null +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/approvaltests/WindowsOrUnixOsEnvironmentLabeller.java @@ -0,0 +1,41 @@ +/* + * Copyright 2023 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. + */ + +package org.keycloak.it.approvaltests; + +import org.lambda.functions.Function0; + +import java.util.Locale; + +public class WindowsOrUnixOsEnvironmentLabeller implements Function0 { + + private static final String WINDOWS_NAME = "windows"; + private static final String UNIX_NAME = "unix"; + + @Override + public String call() + { + String osName = System.getProperty("os.name"); + + if(osName.toLowerCase(Locale.ROOT).contains(WINDOWS_NAME)) { + return WINDOWS_NAME; + } + + //unix suffices, as basically all other OSses use sh files + return UNIX_NAME; + } +} diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HelpCommandDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HelpCommandDistTest.java index 477dd9f3ef..7a59337209 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HelpCommandDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/HelpCommandDistTest.java @@ -21,8 +21,12 @@ import static org.junit.Assert.assertEquals; import static org.keycloak.quarkus.runtime.cli.command.AbstractStartCommand.OPTIMIZED_BUILD_OPTION_LONG; import java.util.List; + +import org.approvaltests.Approvals; +import org.approvaltests.namer.NamedEnvironment; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.OS; +import org.keycloak.it.approvaltests.KcNamerFactory; import org.keycloak.it.junit5.extension.CLIResult; import org.keycloak.it.junit5.extension.DistributionTest; import org.keycloak.it.junit5.extension.RawDistOnly; @@ -44,42 +48,42 @@ public class HelpCommandDistTest { @Launch({}) void testDefaultToHelp(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ "--help" }) void testHelp(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ "-h" }) void testHelpShort(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ Start.NAME, "--help", OPTIMIZED_BUILD_OPTION_LONG}) void testStartOptimizedHelp(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ Start.NAME, "--help" }) void testStartHelp(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ Start.NAME, "--optimized", "--help-all" }) void testStartOptimizedHelpAll(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); cliResult.assertNoMessage("--storage "); } @@ -87,21 +91,21 @@ public class HelpCommandDistTest { @Launch({ StartDev.NAME, "--help" }) void testStartDevHelp(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ StartDev.NAME, "--help-all" }) void testStartDevHelpAll(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ Start.NAME, "--help-all" }) void testStartHelpAll(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); cliResult.assertMessage("--storage"); } @@ -109,35 +113,35 @@ public class HelpCommandDistTest { @Launch({ Build.NAME, "--help" }) void testBuildHelp(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ Export.NAME, "--help" }) void testExportHelp(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ Export.NAME, "--help-all" }) void testExportHelpAll(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ Import.NAME, "--help" }) void testImportHelp(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @Launch({ Import.NAME, "--help-all" }) void testImportHelpAll(LaunchResult result) { CLIResult cliResult = (CLIResult) result; - cliResult.assertHelp(); + assertHelp(cliResult); } @Test @@ -159,4 +163,12 @@ public class HelpCommandDistTest { private void assertSingleJvmStarted(CLIResult run) { assertEquals(1, run.getOutputStream().stream().filter(s -> s.contains("Listening for transport dt_socket")).count()); } + + private void assertHelp(CLIResult result) { + try (NamedEnvironment env = KcNamerFactory.asWindowsOsSpecificTest()) { + Approvals.verify(result.getOutput()); + } catch (Exception cause) { + throw new RuntimeException("Failed to assert help", cause); + } + } } diff --git a/quarkus/tests/junit5/pom.xml b/quarkus/tests/junit5/pom.xml new file mode 100644 index 0000000000..ed201def57 --- /dev/null +++ b/quarkus/tests/junit5/pom.xml @@ -0,0 +1,95 @@ + + + + + 4.0.0 + + + keycloak-quarkus-test-parent + org.keycloak + 999.0.0-SNAPSHOT + ../pom.xml + + + Keycloak Quarkus Server JUnit 5 Internal Test Framework + keycloak-junit5 + jar + + + raw + 14.0.0 + 3.3.0 + + + + + org.keycloak + keycloak-quarkus-server + + + org.keycloak + keycloak-core + + + org.keycloak + keycloak-quarkus-dist + zip + + + + junit + junit + ${junit.version} + compile + + + io.quarkus + quarkus-junit5-internal + + + io.quarkus + quarkus-junit5 + + + org.testcontainers + junit-jupiter + + + org.testcontainers + postgresql + + + org.testcontainers + cockroachdb + + + org.testcontainers + mariadb + + + org.testcontainers + mysql + + + org.apache.maven.wagon + wagon-http-shared + + + diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/Keycloak.java b/quarkus/tests/junit5/src/main/java/org/keycloak/Keycloak.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/Keycloak.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/Keycloak.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/TestProvider.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/TestProvider.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/TestProvider.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/TestProvider.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/BeforeStartDistribution.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/BeforeStartDistribution.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/BeforeStartDistribution.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/BeforeStartDistribution.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java similarity index 92% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java index 77b343fc81..11226d30d6 100644 --- a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java +++ b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java @@ -30,10 +30,7 @@ import java.util.regex.Pattern; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import org.approvaltests.Approvals; import io.quarkus.test.junit.main.LaunchResult; -import org.approvaltests.namer.NamedEnvironment; -import org.keycloak.it.junit5.extension.approvalTests.KcNamerFactory; public interface CLIResult extends LaunchResult { @@ -82,14 +79,6 @@ public interface CLIResult extends LaunchResult { () -> "The Error Output:\n " + getErrorOutput() + "\ndoesn't contains " + msg); } - default void assertHelp() { - try (NamedEnvironment env = KcNamerFactory.asWindowsOsSpecificTest()) { - Approvals.verify(getOutput()); - } catch (Exception cause) { - throw new RuntimeException("Failed to assert help", cause); - } - } - default void assertMessage(String message) { assertThat(getOutput(), containsString(message)); } diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLITest.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITest.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLITest.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITest.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/CLITestExtension.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/DatabaseContainer.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DatabaseContainer.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/DatabaseContainer.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DatabaseContainer.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/DistributionLifecycleManager.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DistributionLifecycleManager.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/DistributionLifecycleManager.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DistributionLifecycleManager.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/DistributionTest.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DistributionTest.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/DistributionTest.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DistributionTest.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/DistributionType.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DistributionType.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/DistributionType.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/DistributionType.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/KeepServerAlive.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/KeepServerAlive.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/KeepServerAlive.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/KeepServerAlive.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/KeycloakDistributionDecorator.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/KeycloakDistributionDecorator.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/KeycloakDistributionDecorator.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/KeycloakDistributionDecorator.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/LegacyStore.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/LegacyStore.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/LegacyStore.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/LegacyStore.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/RawDistOnly.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/RawDistOnly.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/RawDistOnly.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/RawDistOnly.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/ServerOptions.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/ServerOptions.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/ServerOptions.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/ServerOptions.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/TestProvider.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/TestProvider.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/TestProvider.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/TestProvider.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/WithDatabase.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/WithDatabase.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/WithDatabase.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/WithDatabase.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/WithEnvVars.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/WithEnvVars.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/WithEnvVars.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/junit5/extension/WithEnvVars.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/DockerKeycloakDistribution.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/DockerKeycloakDistribution.java similarity index 79% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/utils/DockerKeycloakDistribution.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/DockerKeycloakDistribution.java index d6d33af2e9..f512628b8d 100644 --- a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/DockerKeycloakDistribution.java +++ b/quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/DockerKeycloakDistribution.java @@ -7,10 +7,14 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.output.OutputFrame; import org.testcontainers.containers.output.ToStringConsumer; import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.images.RemoteDockerImage; import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.LazyFuture; import org.testcontainers.utility.ResourceReaper; import java.io.File; +import java.lang.reflect.Field; import java.time.Duration; import java.util.List; import java.util.concurrent.Executor; @@ -27,9 +31,6 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution { private String stdout = ""; private String stderr = ""; private ToStringConsumer backupConsumer = new ToStringConsumer(); - - private File distributionFile = new File("../../dist/target/keycloak-" + Version.VERSION + ".tar.gz"); - private File dockerFile = new File("../../container/Dockerfile"); private File dockerScriptFile = new File("../../container/ubi-null.sh"); private GenericContainer keycloakContainer = null; @@ -43,16 +44,31 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution { } private GenericContainer getKeycloakContainer() { + File distributionFile = new File("../../dist/" + File.separator + "target" + File.separator + "keycloak-" + Version.VERSION + ".tar.gz"); + + if (!distributionFile.exists()) { + distributionFile = Maven.resolveArtifact("org.keycloak", "keycloak-quarkus-dist").toFile(); + } + if (!distributionFile.exists()) { throw new RuntimeException("Distribution archive " + distributionFile.getAbsolutePath() +" doesn't exist"); } - return new GenericContainer( - new ImageFromDockerfile("keycloak-under-test", false) - .withFileFromFile("keycloak.tar.gz", distributionFile) - .withFileFromFile("ubi-null.sh", dockerScriptFile) - .withFileFromFile("Dockerfile", dockerFile) - .withBuildArg("KEYCLOAK_DIST", "keycloak.tar.gz") - ) + + File dockerFile = new File("../../container/Dockerfile"); + LazyFuture image; + + if (dockerFile.exists()) { + image = new ImageFromDockerfile("keycloak-under-test", false) + .withFileFromFile("keycloak.tar.gz", distributionFile) + .withFileFromFile("ubi-null.sh", dockerScriptFile) + .withFileFromFile("Dockerfile", dockerFile) + .withBuildArg("KEYCLOAK_DIST", "keycloak.tar.gz"); + toString(); + } else { + image = new RemoteDockerImage(DockerImageName.parse("quay.io/keycloak/keycloak")); + } + + return new GenericContainer(image) .withExposedPorts(8080) .withStartupAttempts(1) .withStartupTimeout(Duration.ofSeconds(120)) @@ -78,9 +94,6 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution { containerId = keycloakContainer.getContainerId(); waitForStableOutput(); - - // TODO: this is based on a lot of assumptions - io.restassured.RestAssured.port = keycloakContainer.getMappedPort(8080); } catch (Exception cause) { this.exitCode = -1; this.stdout = backupConsumer.toUtf8String(); @@ -90,9 +103,23 @@ public final class DockerKeycloakDistribution implements KeycloakDistribution { LOGGER.warn("Failed to start Keycloak container", cause); } + trySetRestAssuredPort(); + return CLIResult.create(getOutputStream(), getErrorStream(), getExitCode()); } + private void trySetRestAssuredPort() { + try { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Class restAssured = classLoader.loadClass("io.restassured.RestAssured"); + Field port = restAssured.getDeclaredField("port"); + port.set(null, keycloakContainer.getMappedPort(8080)); + } catch (Exception ignore) { + // keeping the workaround to set the container port to restassured + // TODO: better way to expose the port to tests + } + } + // After the web server is responding we are still producing some logs that got checked in the tests private void waitForStableOutput() { int retry = 10; diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/KeycloakDistribution.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/KeycloakDistribution.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/utils/KeycloakDistribution.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/KeycloakDistribution.java diff --git a/quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/Maven.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/Maven.java new file mode 100644 index 0000000000..f3b6e43bce --- /dev/null +++ b/quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/Maven.java @@ -0,0 +1,133 @@ +/* + * Copyright 2022 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. + */ + +package org.keycloak.it.utils; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import io.quarkus.bootstrap.resolver.maven.BootstrapMavenContext; +import io.quarkus.bootstrap.resolver.maven.BootstrapMavenException; +import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver; +import io.quarkus.bootstrap.resolver.maven.workspace.LocalProject; +import io.quarkus.bootstrap.utils.BuildToolHelper; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyFilter; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactDescriptorRequest; +import org.eclipse.aether.resolution.ArtifactDescriptorResult; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResult; +import org.eclipse.aether.resolution.DependencyRequest; +import org.eclipse.aether.resolution.DependencyResolutionException; + +public final class Maven { + + public static Path resolveArtifact(String groupId, String artifactId) { + try { + Path classPathDir = Paths.get(Thread.currentThread().getContextClassLoader().getResource(".").toURI()); + Path projectDir = BuildToolHelper.getProjectDir(classPathDir); + BootstrapMavenContext ctx = new BootstrapMavenContext( + BootstrapMavenContext.config().setPreferPomsFromWorkspace(true).setWorkspaceModuleParentHierarchy(true) + .setCurrentProject(projectDir.toString())); + LocalProject project = ctx.getCurrentProject(); + RepositorySystem repositorySystem = ctx.getRepositorySystem(); + List remoteRepositories = ctx.getRemoteRepositories(); + ArtifactDescriptorResult projectDescriptor = repositorySystem.readArtifactDescriptor( + ctx.getRepositorySystemSession(), + new ArtifactDescriptorRequest() + .setArtifact(new DefaultArtifact(project.getGroupId(), project.getArtifactId(), "pom", project.getVersion())) + .setRepositories(remoteRepositories)); + Artifact artifact = resolveArtifact(groupId, artifactId, projectDescriptor.getDependencies()); + + if (artifact == null) { + resolveArtifact(groupId, artifactId, projectDescriptor.getManagedDependencies()); + } + + if (artifact == null) { + artifact = resolveArtifactRecursively(ctx, projectDescriptor, groupId, artifactId); + } + + if (artifact == null) { + throw new RuntimeException("Failed to resolve artifact [" + groupId + ":" + artifactId + "] from project [" + projectDescriptor.getArtifact() + "] dependency graph"); + } + + return repositorySystem.resolveArtifact( + ctx.getRepositorySystemSession(), + new ArtifactRequest().setArtifact(artifact) + .setRepositories(remoteRepositories)) + .getArtifact().getFile().toPath(); + } catch (Exception cause) { + throw new RuntimeException("Failed to resolve artifact: " + groupId + ":" + artifactId, cause); + } + } + + private static Artifact resolveArtifact(String groupId, String artifactId, List dependencies) { + for (Dependency dependency : dependencies) { + Artifact artifact = dependency.getArtifact(); + + if (artifact.getGroupId().equals(groupId) && artifact.getArtifactId().equals(artifactId)) { + return artifact; + } + } + + return null; + } + + private static Artifact resolveArtifactRecursively(BootstrapMavenContext ctx, ArtifactDescriptorResult artifactDescriptor, String groupId, String artifactId) throws BootstrapMavenException, DependencyResolutionException { + CollectRequest collectRequest = MavenArtifactResolver.newCollectRequest(artifactDescriptor.getArtifact(), artifactDescriptor.getDependencies(), + List.of(), + List.of(), + ctx.getRemoteRepositories()); + List artifactResults = ctx.getRepositorySystem().resolveDependencies(ctx.getRepositorySystemSession(), + new DependencyRequest() + .setFilter(new DependencyFilter() { + @Override + public boolean accept(DependencyNode node, List parents) { + Dependency dependency = node.getDependency(); + + if (dependency == null) { + return false; + } + + Artifact artifact = dependency.getArtifact(); + + return artifact.getGroupId().equals(groupId) + && artifact.getArtifactId().equals(artifactId); + } + }) + .setCollectRequest(collectRequest)) + .getArtifactResults(); + + if (artifactResults.isEmpty()) { + return null; + } + + if (artifactResults.size() > 1) { + throw new RuntimeException("Unexpected number of resolved artifacts: " + artifactResults); + } + + return artifactResults.get(0).getArtifact(); + } +} \ No newline at end of file diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/RawDistRootPath.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/RawDistRootPath.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/utils/RawDistRootPath.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/RawDistRootPath.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/RawKeycloakDistribution.java b/quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/RawKeycloakDistribution.java similarity index 98% rename from quarkus/tests/integration/src/main/java/org/keycloak/it/utils/RawKeycloakDistribution.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/RawKeycloakDistribution.java index a10e39f145..15bb4885b9 100644 --- a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/RawKeycloakDistribution.java +++ b/quarkus/tests/junit5/src/main/java/org/keycloak/it/utils/RawKeycloakDistribution.java @@ -375,11 +375,15 @@ public final class RawKeycloakDistribution implements KeycloakDistribution { distRootPath.toFile().mkdirs(); File distFile = new File("../../dist/" + File.separator + "target" + File.separator + "keycloak-" + Version.VERSION + ".zip"); - if (!distFile.exists()) { - throw new RuntimeException("Distribution archive " + distFile.getAbsolutePath() +" doesn't exist"); + String distDirName; + + if (distFile.exists()) { + distDirName = distFile.getName(); + } else { + distFile = Maven.resolveArtifact("org.keycloak", "keycloak-quarkus-dist").toFile(); + distDirName = distFile.getName().replace("-quarkus-dist", ""); } distRootPath.toFile().mkdirs(); - String distDirName = distFile.getName(); Path dPath = distRootPath.resolve(distDirName.substring(0, distDirName.lastIndexOf('.'))); if (!inited || (reCreate || !dPath.toFile().exists())) { diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/quarkus/runtime/configuration/test/TestConfigArgsConfigSource.java b/quarkus/tests/junit5/src/main/java/org/keycloak/quarkus/runtime/configuration/test/TestConfigArgsConfigSource.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/quarkus/runtime/configuration/test/TestConfigArgsConfigSource.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/quarkus/runtime/configuration/test/TestConfigArgsConfigSource.java diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/quarkus/runtime/configuration/test/TestKeycloakConfigSourceProvider.java b/quarkus/tests/junit5/src/main/java/org/keycloak/quarkus/runtime/configuration/test/TestKeycloakConfigSourceProvider.java similarity index 100% rename from quarkus/tests/integration/src/main/java/org/keycloak/quarkus/runtime/configuration/test/TestKeycloakConfigSourceProvider.java rename to quarkus/tests/junit5/src/main/java/org/keycloak/quarkus/runtime/configuration/test/TestKeycloakConfigSourceProvider.java diff --git a/quarkus/tests/pom.xml b/quarkus/tests/pom.xml index 9c2f2de3d7..434605e1b9 100644 --- a/quarkus/tests/pom.xml +++ b/quarkus/tests/pom.xml @@ -32,6 +32,10 @@ keycloak-quarkus-test-parent pom + + junit5 + + noIntegrations diff --git a/testsuite/integration-arquillian/tests/base/pom.xml b/testsuite/integration-arquillian/tests/base/pom.xml index 05af84f3ae..512f907981 100644 --- a/testsuite/integration-arquillian/tests/base/pom.xml +++ b/testsuite/integration-arquillian/tests/base/pom.xml @@ -180,7 +180,7 @@ org.keycloak - keycloak-quarkus-integration-tests + keycloak-junit5 ${project.version} @@ -1147,7 +1147,7 @@ org.keycloak - keycloak-quarkus-integration-tests + keycloak-junit5 ${project.version}