diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java b/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java index 1714a02868..5d2f7a228d 100644 --- a/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java +++ b/quarkus/tests/integration/src/main/java/org/keycloak/it/junit5/extension/CLIResult.java @@ -20,6 +20,8 @@ package org.keycloak.it.junit5.extension; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import static org.testcontainers.shaded.org.hamcrest.MatcherAssert.assertThat; +import static org.testcontainers.shaded.org.hamcrest.Matchers.containsString; import java.util.List; @@ -40,6 +42,11 @@ public interface CLIResult extends LaunchResult { return outputStream; } + @Override + public String getErrorOutput() { + return String.join("\n", errStream).replace("\r",""); + } + @Override public List getErrorStream() { return errStream; @@ -82,7 +89,7 @@ public interface CLIResult extends LaunchResult { } default void assertMessage(String message) { - assertTrue(getOutput().contains(message)); + assertThat(getOutput(), containsString(message)); } default void assertBuild() { @@ -112,7 +119,7 @@ public interface CLIResult extends LaunchResult { default void assertJsonLogDefaultsApplied() throws JsonProcessingException { ObjectMapper objectMapper = new ObjectMapper(); - String[] splittedOutput = getOutput().split(System.lineSeparator()); + String[] splittedOutput = getOutput().split("\n"); int counter = 0; diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/KeycloakDistribution.java b/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/KeycloakDistribution.java index e5aad15022..4f49a2ad60 100644 --- a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/KeycloakDistribution.java +++ b/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/KeycloakDistribution.java @@ -1,13 +1,14 @@ package org.keycloak.it.utils; +import org.keycloak.quarkus.runtime.Environment; import java.nio.file.Path; -import java.util.ArrayList; import java.util.List; -import static org.keycloak.quarkus.runtime.Environment.LAUNCH_MODE; - public interface KeycloakDistribution { + String SCRIPT_CMD = Environment.isWindows() ? "kc.bat" : "kc.sh"; + String SCRIPT_CMD_INVOKABLE = Environment.isWindows() ? SCRIPT_CMD : "./"+SCRIPT_CMD; + void start(List arguments); void stop(); @@ -23,21 +24,7 @@ public interface KeycloakDistribution { boolean isManualStop(); default String[] getCliArgs(List arguments) { - List commands = new ArrayList<>(); - - commands.add("./kc.sh"); - - if (this.isDebug()) { - commands.add("--debug"); - } - - if (!this.isManualStop()) { - commands.add("-D" + LAUNCH_MODE + "=test"); - } - - commands.addAll(arguments); - - return commands.toArray(new String[0]); + throw new RuntimeException("Not implemented"); } default void setManualStop(boolean manualStop) { diff --git a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/RawKeycloakDistribution.java b/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/RawKeycloakDistribution.java index 805d0d96cf..6b071c2980 100644 --- a/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/RawKeycloakDistribution.java +++ b/quarkus/tests/integration/src/main/java/org/keycloak/it/utils/RawKeycloakDistribution.java @@ -35,11 +35,12 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.Properties; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; @@ -52,6 +53,9 @@ import io.quarkus.fs.util.ZipUtils; import org.apache.commons.io.FileUtils; import org.keycloak.common.Version; +import org.keycloak.quarkus.runtime.Environment; + +import static org.keycloak.quarkus.runtime.Environment.LAUNCH_MODE; public final class RawKeycloakDistribution implements KeycloakDistribution { @@ -104,10 +108,26 @@ public final class RawKeycloakDistribution implements KeycloakDistribution { public void stop() { if (isRunning()) { try { + + if (Environment.isWindows()) { + // On Windows, we're executing kc.bat in a runtime as "keycloak", + // so tha java process is an actual child process + // we have to kill first. + killChildProcessesOnWindows(false); + } + keycloak.destroy(); keycloak.waitFor(10, TimeUnit.SECONDS); exitCode = keycloak.exitValue(); + } catch (Exception cause) { + if (Environment.isWindows()) { + try { + killChildProcessesOnWindows(true); + } catch (Exception e) { + throw new RuntimeException("Failed to stop the server", e); + } + } keycloak.destroyForcibly(); throw new RuntimeException("Failed to stop the server", cause); } @@ -116,32 +136,68 @@ public final class RawKeycloakDistribution implements KeycloakDistribution { shutdownOutputExecutor(); } + private void killChildProcessesOnWindows(boolean isForced) { + for (ProcessHandle childProcessHandle : keycloak.children().collect(Collectors.toList())) { + CompletableFuture onExit = childProcessHandle.onExit(); + if (isForced) { + childProcessHandle.destroyForcibly(); + } else { + childProcessHandle.destroy(); + } + //for whatever reason windows doesnt wait for the termination, + // and parent process returns immediately with exitCode 1 but is not exited, leading to + // "failed to start the distribution" bc files that should be deleted + // are used by another process, so we need this here. + onExit.join(); + } + } + @Override public List getOutputStream() { return outputStream; } + @Override public List getErrorStream() { return errorStream; } + @Override public int getExitCode() { return exitCode; } + @Override public boolean isDebug() { return this.debug; } + @Override public boolean isManualStop() { return this.manualStop; } @Override public String[] getCliArgs(List arguments) { + List allArgs = new ArrayList<>(); + + if (Environment.isWindows()) { + allArgs.add(distPath.resolve("bin") + File.separator + SCRIPT_CMD_INVOKABLE); + } else { + allArgs.add(SCRIPT_CMD_INVOKABLE); + } + + if (this.isDebug()) { + allArgs.add("--debug"); + } + + if (!this.isManualStop()) { + allArgs.add("-D" + LAUNCH_MODE + "=test"); + } + this.relativePath = arguments.stream().filter(arg -> arg.startsWith("--http-relative-path")).map(arg -> arg.substring(arg.indexOf('=') + 1)).findAny().orElse("/"); this.httpPort = Integer.parseInt(arguments.stream().filter(arg -> arg.startsWith("--http-port")).map(arg -> arg.substring(arg.indexOf('=') + 1)).findAny().orElse("8080")); - List args = new ArrayList<>(); - args.add("-Dkc.home.dir=" + distPath + File.separator); - args.addAll(arguments); - return KeycloakDistribution.super.getCliArgs(args); + allArgs.add("-Dkc.home.dir=" + distPath + File.separator); + allArgs.addAll(arguments); + + return allArgs.toArray(String[]::new); } private void waitForReadiness() throws MalformedURLException { @@ -256,32 +312,56 @@ public final class RawKeycloakDistribution implements KeycloakDistribution { try { Path distRootPath = Paths.get(System.getProperty("java.io.tmpdir")).resolve("kc-tests"); distRootPath.toFile().mkdirs(); - File distFile = new File("../../dist/target/keycloak-" + Version.VERSION_KEYCLOAK + ".zip"); + + File distFile = new File("../../dist/" + File.separator + "target" + File.separator + "keycloak-" + Version.VERSION_KEYCLOAK + ".zip"); if (!distFile.exists()) { throw new RuntimeException("Distribution archive " + distFile.getAbsolutePath() +" doesn't exists"); } distRootPath.toFile().mkdirs(); - String distDirName = distFile.getName().replace("keycloak-server-x-dist", "keycloak.x"); - Path distPath = distRootPath.resolve(distDirName.substring(0, distDirName.lastIndexOf('.'))); + String distDirName = distFile.getName(); + Path dPath = distRootPath.resolve(distDirName.substring(0, distDirName.lastIndexOf('.'))); + + if (!inited || (reCreate || !dPath.toFile().exists())) { + + if (!Environment.isWindows()) { + FileUtils.deleteDirectory(dPath.toFile()); + } else { + deleteTempFilesOnWindows(dPath); + } - if (!inited || (reCreate || !distPath.toFile().exists())) { - FileUtils.deleteDirectory(distPath.toFile()); ZipUtils.unzip(distFile.toPath(), distRootPath); } - // make sure kc.sh is executable - if (!distPath.resolve("bin").resolve("kc.sh").toFile().setExecutable(true)) { - throw new RuntimeException("Cannot set kc.sh executable"); + // make sure script is executable + if (!dPath.resolve("bin").resolve(SCRIPT_CMD).toFile().setExecutable(true)) { + throw new RuntimeException("Cannot set " + SCRIPT_CMD + " executable"); } inited = true; - return distPath; + return dPath; } catch (Exception cause) { throw new RuntimeException("Failed to prepare distribution", cause); } } + private void deleteTempFilesOnWindows(Path dPath) { + if (Files.exists(dPath)) { + try (Stream walk = Files.walk(dPath)) { + walk.sorted(Comparator.reverseOrder()) + .forEach(s -> { + try { + Files.delete(s); + } catch (IOException e) { + throw new RuntimeException("Could not delete temp directory for distribution", e); + } + }); + } catch (IOException e) { + throw new RuntimeException("Could not traverse temp directory for distribution to delete files", e); + } + } + } + private void readOutput() { try ( BufferedReader outStream = new BufferedReader(new InputStreamReader(keycloak.getInputStream())); diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/OptionValidationTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/OptionValidationTest.java index f784dfa0e6..6d3f5bbf7c 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/OptionValidationTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/OptionValidationTest.java @@ -18,13 +18,16 @@ package org.keycloak.it.cli; import org.junit.jupiter.api.Test; +import org.keycloak.it.junit5.extension.CLIResult; import org.keycloak.it.junit5.extension.CLITest; import io.quarkus.test.junit.main.Launch; import io.quarkus.test.junit.main.LaunchResult; +import org.keycloak.it.utils.KeycloakDistribution; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; @CLITest public class OptionValidationTest { @@ -32,43 +35,49 @@ public class OptionValidationTest { @Test @Launch({"build", "--db"}) public void failMissingOptionValue(LaunchResult result) { - assertTrue(result.getErrorOutput().contains("Missing required value for option '--db' (vendor). Expected values are: dev-file, dev-mem, mariadb, mssql, mysql, oracle, postgres")); + CLIResult cliResult = (CLIResult) result; + assertThat(cliResult.getErrorOutput(), containsString("Missing required value for option '--db' (vendor). Expected values are: dev-file, dev-mem, mariadb, mssql, mysql, oracle, postgres")); } @Test @Launch({"build", "--db", "foo", "bar"}) public void failMultipleOptionValue(LaunchResult result) { - assertTrue(result.getErrorOutput().contains("Option '--db' expects a single value (vendor) Expected values are: dev-file, dev-mem, mariadb, mssql, mysql, oracle, postgres")); + CLIResult cliResult = (CLIResult) result; + assertThat(cliResult.getErrorOutput(), containsString("Option '--db' expects a single value (vendor) Expected values are: dev-file, dev-mem, mariadb, mssql, mysql, oracle, postgres")); } @Test @Launch({"build", "--nosuch"}) public void failUnknownOption(LaunchResult result) { + CLIResult cliResult = (CLIResult) result; assertEquals("Unknown option: '--nosuch'\n" + - "Try 'kc.sh build --help' for more information on the available options.", result.getErrorOutput()); + "Try '" + KeycloakDistribution.SCRIPT_CMD + " build --help' for more information on the available options.", cliResult.getErrorOutput()); } @Test @Launch({"start", "--db-pasword mytestpw"}) public void failUnknownOptionWhitespaceSeparatorNotShowingValue(LaunchResult result) { + CLIResult cliResult = (CLIResult) result; assertEquals("Unknown option: '--db-pasword'\n" + "Possible solutions: --db-username, --db-url-host, --db-pool-min-size, --db-password, --db-url-properties, --db-url-database, --db-schema, --db-pool-max-size, --db-pool-initial-size, --db-url, --db-url-port\n" + - "Try 'kc.sh start --help' for more information on the available options.", result.getErrorOutput()); + "Try '" + KeycloakDistribution.SCRIPT_CMD + " start --help' for more information on the available options.", cliResult.getErrorOutput()); } @Test @Launch({"start", "--db-pasword=mytestpw"}) public void failUnknownOptionEqualsSeparatorNotShowingValue(LaunchResult result) { + CLIResult cliResult = (CLIResult) result; assertEquals("Unknown option: '--db-pasword'\n" + "Possible solutions: --db-username, --db-url-host, --db-pool-min-size, --db-password, --db-url-properties, --db-url-database, --db-schema, --db-pool-max-size, --db-pool-initial-size, --db-url, --db-url-port\n" + - "Try 'kc.sh start --help' for more information on the available options.", result.getErrorOutput()); + "Try '" + KeycloakDistribution.SCRIPT_CMD + " start --help' for more information on the available options.", cliResult.getErrorOutput()); } @Test @Launch({"start", "--db-username=foobar","--db-pasword=mytestpw", "--foobar=barfoo"}) public void failWithFirstOptionOnMultipleUnknownOptions(LaunchResult result) { + CLIResult cliResult = (CLIResult) result; assertEquals("Unknown option: '--db-pasword'\n" + "Possible solutions: --db-username, --db-url-host, --db-pool-min-size, --db-password, --db-url-properties, --db-url-database, --db-schema, --db-pool-max-size, --db-pool-initial-size, --db-url, --db-url-port\n" + - "Try 'kc.sh start --help' for more information on the available options.", result.getErrorOutput()); + "Try '" + KeycloakDistribution.SCRIPT_CMD + " start --help' for more information on the available options.", cliResult.getErrorOutput()); } } diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/BuildCommandDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/BuildCommandDistTest.java index ff89b06e6e..cb4a9dad58 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/BuildCommandDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/BuildCommandDistTest.java @@ -26,6 +26,7 @@ import org.keycloak.it.junit5.extension.DistributionTest; import io.quarkus.test.junit.main.Launch; import io.quarkus.test.junit.main.LaunchResult; +import org.keycloak.it.utils.KeycloakDistribution; @DistributionTest class BuildCommandDistTest { @@ -39,7 +40,7 @@ class BuildCommandDistTest { () -> "The Output:\n" + result.getOutput() + "doesn't contains the expected string."); assertTrue(result.getOutput().contains("Server configuration updated and persisted. Run the following command to review the configuration:"), () -> "The Output:\n" + result.getOutput() + "doesn't contains the expected string."); - assertTrue(result.getOutput().contains("kc.sh show-config"), + assertTrue(result.getOutput().contains(KeycloakDistribution.SCRIPT_CMD + " show-config"), () -> "The Output:\n" + result.getOutput() + "doesn't contains the expected string."); } diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/ClusterConfigDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/ClusterConfigDistTest.java index 6f68c37d42..41b5933948 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/ClusterConfigDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/ClusterConfigDistTest.java @@ -22,6 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.file.Path; import java.util.function.Consumer; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; import org.keycloak.it.junit5.extension.BeforeStartDistribution; import org.keycloak.it.junit5.extension.CLIResult; import org.keycloak.it.junit5.extension.DistributionTest; @@ -69,12 +71,23 @@ public class ClusterConfigDistTest { } @Test - @Launch({ "start", "--auto-build", "--http-enabled=true", "--hostname-strict false" }) + @EnabledOnOs(value = { OS.LINUX, OS.MAC }, disabledReason = "different shell escaping behaviour on Windows.") + @Launch({ "start", "--auto-build", "--log-level=info,org.infinispan.remoting.transport.jgroups.JGroupsTransport:debug","--http-enabled=true", "--hostname-strict=false" }) void testStartDefaultsToClustering(LaunchResult result) { CLIResult cliResult = (CLIResult) result; cliResult.assertStarted(); cliResult.assertClusteredCache(); - assertTrue(cliResult.getOutput().contains("org.jgroups.protocols.UDP")); + assertTrue(cliResult.getOutput().contains("JGroups protocol stack: UDP")); + } + + @Test + @EnabledOnOs(value = { OS.WINDOWS }, disabledReason = "different shell behaviour on Windows.") + @Launch({ "start", "--auto-build", "--log-level=\"info,org.infinispan.remoting.transport.jgroups.JGroupsTransport:debug","--http-enabled=true\"", "--hostname-strict=false" }) + void testWinStartDefaultsToClustering(LaunchResult result) { + CLIResult cliResult = (CLIResult) result; + cliResult.assertStarted(); + cliResult.assertClusteredCache(); + assertTrue(cliResult.getOutput().contains("JGroups protocol stack: UDP")); } @Test diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FeaturesDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FeaturesDistTest.java index 89f63082f0..1f7f0bb179 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FeaturesDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FeaturesDistTest.java @@ -7,6 +7,8 @@ import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; import org.keycloak.it.junit5.extension.CLIResult; import org.keycloak.it.junit5.extension.DistributionTest; import org.keycloak.it.junit5.extension.RawDistOnly; @@ -56,6 +58,7 @@ public class FeaturesDistTest { } @Test + @EnabledOnOs(value = { OS.LINUX, OS.MAC }, disabledReason = "different shell escaping behaviour on Windows.") @Launch({StartDev.NAME, "--features=token-exchange,admin-fine-grained-authz"}) public void testEnableMultipleFeatures(LaunchResult result) { CLIResult cliResult = (CLIResult) result; @@ -66,6 +69,18 @@ public class FeaturesDistTest { assertFalse(cliResult.getOutput().contains("declarative-user-profile")); } + @Test + @EnabledOnOs(value = { OS.WINDOWS }, disabledReason = "different shell escaping behaviour on Windows.") + @Launch({StartDev.NAME, "--features=\"token-exchange,admin-fine-grained-authz\""}) + public void testWinEnableMultipleFeatures(LaunchResult result) { + CLIResult cliResult = (CLIResult) result; + cliResult.assertStartedDevMode(); + assertThat(cliResult.getOutput(), CoreMatchers.allOf( + containsString("Preview feature enabled: admin_fine_grained_authz"), + containsString("Preview feature enabled: token_exchange"))); + assertFalse(cliResult.getOutput().contains("declarative-user-profile")); + } + private void assertPreviewFeaturesEnabled(CLIResult result) { assertThat(result.getOutput(), CoreMatchers.allOf( containsString("Preview feature enabled: admin_fine_grained_authz"), diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/LoggingDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/LoggingDistTest.java index 41533a37e0..9b25963e3f 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/LoggingDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/LoggingDistTest.java @@ -22,6 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import com.fasterxml.jackson.core.JsonProcessingException; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; import org.keycloak.it.junit5.extension.CLIResult; import org.keycloak.it.junit5.extension.DistributionTest; import org.keycloak.it.junit5.extension.RawDistOnly; @@ -60,6 +62,7 @@ public class LoggingDistTest { } @Test + @EnabledOnOs(value = { OS.LINUX, OS.MAC }, disabledReason = "different shell escaping behaviour on Windows.") @Launch({ "start-dev", "--log-level=off,org.keycloak:debug,org.infinispan:info" }) void testRootAndCategoryLevels(LaunchResult result) { CLIResult cliResult = (CLIResult) result; @@ -69,6 +72,17 @@ public class LoggingDistTest { } @Test + @EnabledOnOs(value = { OS.WINDOWS }, disabledReason = "different shell escaping behaviour on Windows.") + @Launch({ "start-dev", "--log-level=\"off,org.keycloak:debug,org.infinispan:info\"" }) + void testWinRootAndCategoryLevels(LaunchResult result) { + CLIResult cliResult = (CLIResult) result; + assertFalse(cliResult.getOutput().contains("INFO [io.quarkus")); + assertTrue(cliResult.getOutput().contains("DEBUG [org.keycloak")); + assertTrue(cliResult.getOutput().contains("INFO [org.infinispan.CONTAINER]")); + } + + @Test + @EnabledOnOs(value = { OS.LINUX, OS.MAC }, disabledReason = "different shell escaping behaviour on Windows.") @Launch({ "start-dev", "--log-level=off,org.keycloak:warn,debug" }) void testSetLastRootLevelIfMultipleSet(LaunchResult result) { CLIResult cliResult = (CLIResult) result; @@ -78,6 +92,17 @@ public class LoggingDistTest { } @Test + @EnabledOnOs(value = { OS.WINDOWS }, disabledReason = "different shell escaping behaviour on Windows.") + @Launch({ "start-dev", "--log-level=\"off,org.keycloak:warn,debug\"" }) + void testWinSetLastRootLevelIfMultipleSet(LaunchResult result) { + CLIResult cliResult = (CLIResult) result; + assertTrue(cliResult.getOutput().contains("DEBUG [org.hibernate")); + assertFalse(cliResult.getOutput().contains("INFO [org.keycloak")); + cliResult.assertStartedDevMode(); + } + + @Test + @EnabledOnOs(value = { OS.LINUX, OS.MAC }, disabledReason = "different shell escaping behaviour on Windows.") @Launch({ "start-dev", "--log-console-format=\"%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{1.}] %s%e%n\"" }) void testSetLogFormat(LaunchResult result) { CLIResult cliResult = (CLIResult) result; @@ -94,6 +119,7 @@ public class LoggingDistTest { } @Test + @EnabledOnOs(value = { OS.LINUX, OS.MAC }, disabledReason = "different shell escaping behaviour on Windows.") @Launch({ "start-dev", "--log-level=off,org.keycloak:debug,org.infinispan:info", "--log-console-output=json" }) void testLogLevelSettingsAppliedWhenJsonEnabled(LaunchResult result) { CLIResult cliResult = (CLIResult) result; @@ -103,6 +129,17 @@ public class LoggingDistTest { } @Test + @EnabledOnOs(value = { OS.WINDOWS }, disabledReason = "different shell escaping behaviour on Windows.") + @Launch({ "start-dev", "--log-level=\"off,org.keycloak:debug,org.infinispan:info\"", "--log-console-output=json" }) + void testWinLogLevelSettingsAppliedWhenJsonEnabled(LaunchResult result) { + CLIResult cliResult = (CLIResult) result; + assertFalse(cliResult.getOutput().contains("\"loggerName\":\"io.quarkus\",\"level\":\"INFO\")")); + assertTrue(cliResult.getOutput().contains("\"loggerName\":\"org.keycloak.quarkus.runtime.storage.database.jpa.QuarkusJpaConnectionProviderFactory\",\"level\":\"DEBUG\"")); + assertTrue(cliResult.getOutput().contains("\"loggerName\":\"org.infinispan.CONTAINER\",\"level\":\"INFO\"")); + } + + @Test + @EnabledOnOs(value = { OS.LINUX, OS.MAC }, disabledReason = "different shell escaping behaviour on Windows.") @Launch({ "start-dev", "--log=console,file"}) void testKeycloakLogFileCreated(RawDistRootPath path) { Path logFilePath = Paths.get(path.getDistRootPath() + File.separator + LoggingPropertyMappers.DEFAULT_LOG_PATH); @@ -111,6 +148,16 @@ public class LoggingDistTest { } @Test + @EnabledOnOs(value = { OS.WINDOWS }, disabledReason = "different shell escaping behaviour on Windows.") + @Launch({ "start-dev", "--log=\"console,file\""}) + void testWinKeycloakLogFileCreated(RawDistRootPath path) { + Path logFilePath = Paths.get(path.getDistRootPath() + File.separator + LoggingPropertyMappers.DEFAULT_LOG_PATH); + File logFile = new File(logFilePath.toString()); + assertTrue(logFile.isFile(), "Log file does not exist!"); + } + + @Test + @EnabledOnOs(value = { OS.LINUX, OS.MAC }, disabledReason = "different shell escaping behaviour on Windows.") @Launch({ "start-dev", "--log=console,file", "--log-file-format=\"%d{HH:mm:ss} %-5p [%c{1.}] (%t) %s%e%n\""}) void testFileLoggingHasDifferentFormat(RawDistRootPath path) throws IOException { Path logFilePath = Paths.get(path.getDistRootPath() + File.separator + LoggingPropertyMappers.DEFAULT_LOG_PATH); diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/StartAutoBuildDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/StartAutoBuildDistTest.java index 567e10d16e..7eaa26cd6a 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/StartAutoBuildDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/StartAutoBuildDistTest.java @@ -30,6 +30,7 @@ import org.keycloak.it.junit5.extension.RawDistOnly; import io.quarkus.test.junit.main.Launch; import io.quarkus.test.junit.main.LaunchResult; +import org.keycloak.it.utils.KeycloakDistribution; @DistributionTest(reInstall = DistributionTest.ReInstall.NEVER) @RawDistOnly(reason = "Containers are immutable") @@ -44,9 +45,9 @@ public class StartAutoBuildDistTest { cliResult.assertMessage("Changes detected in configuration. Updating the server image."); cliResult.assertMessage("Updating the configuration and installing your custom providers, if any. Please wait."); cliResult.assertMessage("Server configuration updated and persisted. Run the following command to review the configuration:"); - cliResult.assertMessage("kc.sh show-config"); + cliResult.assertMessage(KeycloakDistribution.SCRIPT_CMD + " show-config"); cliResult.assertMessage("Next time you run the server, just run:"); - cliResult.assertMessage("kc.sh start --http-enabled=true --hostname-strict=false"); + cliResult.assertMessage(KeycloakDistribution.SCRIPT_CMD + " start --http-enabled=true --hostname-strict=false"); assertFalse(cliResult.getOutput().contains("--cache")); cliResult.assertStarted(); } diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/StartCommandDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/StartCommandDistTest.java index d0b877e000..cab9904bdd 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/StartCommandDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/StartCommandDistTest.java @@ -17,6 +17,8 @@ package org.keycloak.it.cli.dist; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -28,16 +30,17 @@ import org.keycloak.it.junit5.extension.DistributionTest; import io.quarkus.test.junit.main.Launch; import io.quarkus.test.junit.main.LaunchResult; +import org.keycloak.it.utils.KeycloakDistribution; @DistributionTest public class StartCommandDistTest extends StartCommandTest { @Test - @Launch({ "-pf=dev", "start", "--auto-build", "--http-enabled=true", "--hostname-strict=false" }) + @Launch({ "--profile=dev", "start", "--auto-build", "--http-enabled=true", "--hostname-strict=false" }) void failIfAutoBuildUsingDevProfile(LaunchResult result) { - assertTrue(result.getErrorOutput().contains("You can not 'start' the server in development mode. Please re-build the server first, using 'kc.sh build' for the default production mode."), - () -> "The Output:\n" + result.getErrorOutput() + "doesn't contains the expected string."); - assertEquals(4, result.getErrorStream().size()); + CLIResult cliResult = (CLIResult) result; + assertThat(cliResult.getErrorOutput(), containsString("You can not 'start' the server in development mode. Please re-build the server first, using 'kc.sh build' for the default production mode.")); + assertEquals(4, cliResult.getErrorStream().size()); } @Test @@ -54,9 +57,9 @@ public class StartCommandDistTest extends StartCommandTest { cliResult.assertMessage("Changes detected in configuration. Updating the server image."); cliResult.assertMessage("Updating the configuration and installing your custom providers, if any. Please wait."); cliResult.assertMessage("Server configuration updated and persisted. Run the following command to review the configuration:"); - cliResult.assertMessage("kc.sh show-config"); + cliResult.assertMessage(KeycloakDistribution.SCRIPT_CMD + " show-config"); cliResult.assertMessage("Next time you run the server, just run:"); - cliResult.assertMessage("kc.sh start --http-enabled=true --hostname-strict=false"); + cliResult.assertMessage(KeycloakDistribution.SCRIPT_CMD + " start --http-enabled=true --hostname-strict=false"); assertFalse(cliResult.getOutput().contains("--cache")); cliResult.assertStarted(); }