parent
eab2dff979
commit
1162952432
10 changed files with 217 additions and 54 deletions
|
@ -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.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -40,6 +42,11 @@ public interface CLIResult extends LaunchResult {
|
||||||
return outputStream;
|
return outputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorOutput() {
|
||||||
|
return String.join("\n", errStream).replace("\r","");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getErrorStream() {
|
public List<String> getErrorStream() {
|
||||||
return errStream;
|
return errStream;
|
||||||
|
@ -82,7 +89,7 @@ public interface CLIResult extends LaunchResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
default void assertMessage(String message) {
|
default void assertMessage(String message) {
|
||||||
assertTrue(getOutput().contains(message));
|
assertThat(getOutput(), containsString(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
default void assertBuild() {
|
default void assertBuild() {
|
||||||
|
@ -112,7 +119,7 @@ public interface CLIResult extends LaunchResult {
|
||||||
default void assertJsonLogDefaultsApplied() throws JsonProcessingException {
|
default void assertJsonLogDefaultsApplied() throws JsonProcessingException {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
String[] splittedOutput = getOutput().split(System.lineSeparator());
|
String[] splittedOutput = getOutput().split("\n");
|
||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
package org.keycloak.it.utils;
|
package org.keycloak.it.utils;
|
||||||
|
|
||||||
|
import org.keycloak.quarkus.runtime.Environment;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.keycloak.quarkus.runtime.Environment.LAUNCH_MODE;
|
|
||||||
|
|
||||||
public interface KeycloakDistribution {
|
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<String> arguments);
|
void start(List<String> arguments);
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
@ -23,21 +24,7 @@ public interface KeycloakDistribution {
|
||||||
boolean isManualStop();
|
boolean isManualStop();
|
||||||
|
|
||||||
default String[] getCliArgs(List<String> arguments) {
|
default String[] getCliArgs(List<String> arguments) {
|
||||||
List<String> commands = new ArrayList<>();
|
throw new RuntimeException("Not implemented");
|
||||||
|
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default void setManualStop(boolean manualStop) {
|
default void setManualStop(boolean manualStop) {
|
||||||
|
|
|
@ -35,11 +35,12 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.stream.Stream;
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
@ -52,6 +53,9 @@ import io.quarkus.fs.util.ZipUtils;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
import org.keycloak.common.Version;
|
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 {
|
public final class RawKeycloakDistribution implements KeycloakDistribution {
|
||||||
|
|
||||||
|
@ -104,10 +108,26 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
||||||
public void stop() {
|
public void stop() {
|
||||||
if (isRunning()) {
|
if (isRunning()) {
|
||||||
try {
|
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.destroy();
|
||||||
keycloak.waitFor(10, TimeUnit.SECONDS);
|
keycloak.waitFor(10, TimeUnit.SECONDS);
|
||||||
exitCode = keycloak.exitValue();
|
exitCode = keycloak.exitValue();
|
||||||
|
|
||||||
} catch (Exception cause) {
|
} catch (Exception cause) {
|
||||||
|
if (Environment.isWindows()) {
|
||||||
|
try {
|
||||||
|
killChildProcessesOnWindows(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to stop the server", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
keycloak.destroyForcibly();
|
keycloak.destroyForcibly();
|
||||||
throw new RuntimeException("Failed to stop the server", cause);
|
throw new RuntimeException("Failed to stop the server", cause);
|
||||||
}
|
}
|
||||||
|
@ -116,32 +136,68 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
||||||
shutdownOutputExecutor();
|
shutdownOutputExecutor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void killChildProcessesOnWindows(boolean isForced) {
|
||||||
|
for (ProcessHandle childProcessHandle : keycloak.children().collect(Collectors.toList())) {
|
||||||
|
CompletableFuture<ProcessHandle> 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
|
@Override
|
||||||
public List<String> getOutputStream() {
|
public List<String> getOutputStream() {
|
||||||
return outputStream;
|
return outputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getErrorStream() {
|
public List<String> getErrorStream() {
|
||||||
return errorStream;
|
return errorStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getExitCode() {
|
public int getExitCode() {
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDebug() { return this.debug; }
|
public boolean isDebug() { return this.debug; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isManualStop() { return this.manualStop; }
|
public boolean isManualStop() { return this.manualStop; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getCliArgs(List<String> arguments) {
|
public String[] getCliArgs(List<String> arguments) {
|
||||||
|
List<String> 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.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"));
|
this.httpPort = Integer.parseInt(arguments.stream().filter(arg -> arg.startsWith("--http-port")).map(arg -> arg.substring(arg.indexOf('=') + 1)).findAny().orElse("8080"));
|
||||||
List<String> 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 {
|
private void waitForReadiness() throws MalformedURLException {
|
||||||
|
@ -256,32 +312,56 @@ public final class RawKeycloakDistribution implements KeycloakDistribution {
|
||||||
try {
|
try {
|
||||||
Path distRootPath = Paths.get(System.getProperty("java.io.tmpdir")).resolve("kc-tests");
|
Path distRootPath = Paths.get(System.getProperty("java.io.tmpdir")).resolve("kc-tests");
|
||||||
distRootPath.toFile().mkdirs();
|
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()) {
|
if (!distFile.exists()) {
|
||||||
throw new RuntimeException("Distribution archive " + distFile.getAbsolutePath() +" doesn't exists");
|
throw new RuntimeException("Distribution archive " + distFile.getAbsolutePath() +" doesn't exists");
|
||||||
}
|
}
|
||||||
distRootPath.toFile().mkdirs();
|
distRootPath.toFile().mkdirs();
|
||||||
String distDirName = distFile.getName().replace("keycloak-server-x-dist", "keycloak.x");
|
String distDirName = distFile.getName();
|
||||||
Path distPath = distRootPath.resolve(distDirName.substring(0, distDirName.lastIndexOf('.')));
|
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);
|
ZipUtils.unzip(distFile.toPath(), distRootPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure kc.sh is executable
|
// make sure script is executable
|
||||||
if (!distPath.resolve("bin").resolve("kc.sh").toFile().setExecutable(true)) {
|
if (!dPath.resolve("bin").resolve(SCRIPT_CMD).toFile().setExecutable(true)) {
|
||||||
throw new RuntimeException("Cannot set kc.sh executable");
|
throw new RuntimeException("Cannot set " + SCRIPT_CMD + " executable");
|
||||||
}
|
}
|
||||||
|
|
||||||
inited = true;
|
inited = true;
|
||||||
|
|
||||||
return distPath;
|
return dPath;
|
||||||
} catch (Exception cause) {
|
} catch (Exception cause) {
|
||||||
throw new RuntimeException("Failed to prepare distribution", cause);
|
throw new RuntimeException("Failed to prepare distribution", cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void deleteTempFilesOnWindows(Path dPath) {
|
||||||
|
if (Files.exists(dPath)) {
|
||||||
|
try (Stream<Path> 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() {
|
private void readOutput() {
|
||||||
try (
|
try (
|
||||||
BufferedReader outStream = new BufferedReader(new InputStreamReader(keycloak.getInputStream()));
|
BufferedReader outStream = new BufferedReader(new InputStreamReader(keycloak.getInputStream()));
|
||||||
|
|
|
@ -18,13 +18,16 @@
|
||||||
package org.keycloak.it.cli;
|
package org.keycloak.it.cli;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.keycloak.it.junit5.extension.CLIResult;
|
||||||
import org.keycloak.it.junit5.extension.CLITest;
|
import org.keycloak.it.junit5.extension.CLITest;
|
||||||
|
|
||||||
import io.quarkus.test.junit.main.Launch;
|
import io.quarkus.test.junit.main.Launch;
|
||||||
import io.quarkus.test.junit.main.LaunchResult;
|
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.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
@CLITest
|
@CLITest
|
||||||
public class OptionValidationTest {
|
public class OptionValidationTest {
|
||||||
|
@ -32,43 +35,49 @@ public class OptionValidationTest {
|
||||||
@Test
|
@Test
|
||||||
@Launch({"build", "--db"})
|
@Launch({"build", "--db"})
|
||||||
public void failMissingOptionValue(LaunchResult result) {
|
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
|
@Test
|
||||||
@Launch({"build", "--db", "foo", "bar"})
|
@Launch({"build", "--db", "foo", "bar"})
|
||||||
public void failMultipleOptionValue(LaunchResult result) {
|
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
|
@Test
|
||||||
@Launch({"build", "--nosuch"})
|
@Launch({"build", "--nosuch"})
|
||||||
public void failUnknownOption(LaunchResult result) {
|
public void failUnknownOption(LaunchResult result) {
|
||||||
|
CLIResult cliResult = (CLIResult) result;
|
||||||
assertEquals("Unknown option: '--nosuch'\n" +
|
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
|
@Test
|
||||||
@Launch({"start", "--db-pasword mytestpw"})
|
@Launch({"start", "--db-pasword mytestpw"})
|
||||||
public void failUnknownOptionWhitespaceSeparatorNotShowingValue(LaunchResult result) {
|
public void failUnknownOptionWhitespaceSeparatorNotShowingValue(LaunchResult result) {
|
||||||
|
CLIResult cliResult = (CLIResult) result;
|
||||||
assertEquals("Unknown option: '--db-pasword'\n" +
|
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" +
|
"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
|
@Test
|
||||||
@Launch({"start", "--db-pasword=mytestpw"})
|
@Launch({"start", "--db-pasword=mytestpw"})
|
||||||
public void failUnknownOptionEqualsSeparatorNotShowingValue(LaunchResult result) {
|
public void failUnknownOptionEqualsSeparatorNotShowingValue(LaunchResult result) {
|
||||||
|
CLIResult cliResult = (CLIResult) result;
|
||||||
assertEquals("Unknown option: '--db-pasword'\n" +
|
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" +
|
"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
|
@Test
|
||||||
@Launch({"start", "--db-username=foobar","--db-pasword=mytestpw", "--foobar=barfoo"})
|
@Launch({"start", "--db-username=foobar","--db-pasword=mytestpw", "--foobar=barfoo"})
|
||||||
public void failWithFirstOptionOnMultipleUnknownOptions(LaunchResult result) {
|
public void failWithFirstOptionOnMultipleUnknownOptions(LaunchResult result) {
|
||||||
|
CLIResult cliResult = (CLIResult) result;
|
||||||
assertEquals("Unknown option: '--db-pasword'\n" +
|
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" +
|
"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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
|
|
||||||
import io.quarkus.test.junit.main.Launch;
|
import io.quarkus.test.junit.main.Launch;
|
||||||
import io.quarkus.test.junit.main.LaunchResult;
|
import io.quarkus.test.junit.main.LaunchResult;
|
||||||
|
import org.keycloak.it.utils.KeycloakDistribution;
|
||||||
|
|
||||||
@DistributionTest
|
@DistributionTest
|
||||||
class BuildCommandDistTest {
|
class BuildCommandDistTest {
|
||||||
|
@ -39,7 +40,7 @@ class BuildCommandDistTest {
|
||||||
() -> "The Output:\n" + result.getOutput() + "doesn't contains the expected string.");
|
() -> "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:"),
|
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.");
|
() -> "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.");
|
() -> "The Output:\n" + result.getOutput() + "doesn't contains the expected string.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import org.junit.jupiter.api.Test;
|
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.BeforeStartDistribution;
|
||||||
import org.keycloak.it.junit5.extension.CLIResult;
|
import org.keycloak.it.junit5.extension.CLIResult;
|
||||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
|
@ -69,12 +71,23 @@ public class ClusterConfigDistTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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) {
|
void testStartDefaultsToClustering(LaunchResult result) {
|
||||||
CLIResult cliResult = (CLIResult) result;
|
CLIResult cliResult = (CLIResult) result;
|
||||||
cliResult.assertStarted();
|
cliResult.assertStarted();
|
||||||
cliResult.assertClusteredCache();
|
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
|
@Test
|
||||||
|
|
|
@ -7,6 +7,8 @@ import org.junit.jupiter.api.MethodOrderer;
|
||||||
import org.junit.jupiter.api.Order;
|
import org.junit.jupiter.api.Order;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.TestMethodOrder;
|
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.CLIResult;
|
||||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||||
|
@ -56,6 +58,7 @@ public class FeaturesDistTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@EnabledOnOs(value = { OS.LINUX, OS.MAC }, disabledReason = "different shell escaping behaviour on Windows.")
|
||||||
@Launch({StartDev.NAME, "--features=token-exchange,admin-fine-grained-authz"})
|
@Launch({StartDev.NAME, "--features=token-exchange,admin-fine-grained-authz"})
|
||||||
public void testEnableMultipleFeatures(LaunchResult result) {
|
public void testEnableMultipleFeatures(LaunchResult result) {
|
||||||
CLIResult cliResult = (CLIResult) result;
|
CLIResult cliResult = (CLIResult) result;
|
||||||
|
@ -66,6 +69,18 @@ public class FeaturesDistTest {
|
||||||
assertFalse(cliResult.getOutput().contains("declarative-user-profile"));
|
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) {
|
private void assertPreviewFeaturesEnabled(CLIResult result) {
|
||||||
assertThat(result.getOutput(), CoreMatchers.allOf(
|
assertThat(result.getOutput(), CoreMatchers.allOf(
|
||||||
containsString("Preview feature enabled: admin_fine_grained_authz"),
|
containsString("Preview feature enabled: admin_fine_grained_authz"),
|
||||||
|
|
|
@ -22,6 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import org.junit.jupiter.api.Test;
|
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.CLIResult;
|
||||||
import org.keycloak.it.junit5.extension.DistributionTest;
|
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||||
|
@ -60,6 +62,7 @@ public class LoggingDistTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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" })
|
@Launch({ "start-dev", "--log-level=off,org.keycloak:debug,org.infinispan:info" })
|
||||||
void testRootAndCategoryLevels(LaunchResult result) {
|
void testRootAndCategoryLevels(LaunchResult result) {
|
||||||
CLIResult cliResult = (CLIResult) result;
|
CLIResult cliResult = (CLIResult) result;
|
||||||
|
@ -69,6 +72,17 @@ public class LoggingDistTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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" })
|
@Launch({ "start-dev", "--log-level=off,org.keycloak:warn,debug" })
|
||||||
void testSetLastRootLevelIfMultipleSet(LaunchResult result) {
|
void testSetLastRootLevelIfMultipleSet(LaunchResult result) {
|
||||||
CLIResult cliResult = (CLIResult) result;
|
CLIResult cliResult = (CLIResult) result;
|
||||||
|
@ -78,6 +92,17 @@ public class LoggingDistTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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\"" })
|
@Launch({ "start-dev", "--log-console-format=\"%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{1.}] %s%e%n\"" })
|
||||||
void testSetLogFormat(LaunchResult result) {
|
void testSetLogFormat(LaunchResult result) {
|
||||||
CLIResult cliResult = (CLIResult) result;
|
CLIResult cliResult = (CLIResult) result;
|
||||||
|
@ -94,6 +119,7 @@ public class LoggingDistTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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" })
|
@Launch({ "start-dev", "--log-level=off,org.keycloak:debug,org.infinispan:info", "--log-console-output=json" })
|
||||||
void testLogLevelSettingsAppliedWhenJsonEnabled(LaunchResult result) {
|
void testLogLevelSettingsAppliedWhenJsonEnabled(LaunchResult result) {
|
||||||
CLIResult cliResult = (CLIResult) result;
|
CLIResult cliResult = (CLIResult) result;
|
||||||
|
@ -103,6 +129,17 @@ public class LoggingDistTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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"})
|
@Launch({ "start-dev", "--log=console,file"})
|
||||||
void testKeycloakLogFileCreated(RawDistRootPath path) {
|
void testKeycloakLogFileCreated(RawDistRootPath path) {
|
||||||
Path logFilePath = Paths.get(path.getDistRootPath() + File.separator + LoggingPropertyMappers.DEFAULT_LOG_PATH);
|
Path logFilePath = Paths.get(path.getDistRootPath() + File.separator + LoggingPropertyMappers.DEFAULT_LOG_PATH);
|
||||||
|
@ -111,6 +148,16 @@ public class LoggingDistTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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\""})
|
@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 {
|
void testFileLoggingHasDifferentFormat(RawDistRootPath path) throws IOException {
|
||||||
Path logFilePath = Paths.get(path.getDistRootPath() + File.separator + LoggingPropertyMappers.DEFAULT_LOG_PATH);
|
Path logFilePath = Paths.get(path.getDistRootPath() + File.separator + LoggingPropertyMappers.DEFAULT_LOG_PATH);
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||||
|
|
||||||
import io.quarkus.test.junit.main.Launch;
|
import io.quarkus.test.junit.main.Launch;
|
||||||
import io.quarkus.test.junit.main.LaunchResult;
|
import io.quarkus.test.junit.main.LaunchResult;
|
||||||
|
import org.keycloak.it.utils.KeycloakDistribution;
|
||||||
|
|
||||||
@DistributionTest(reInstall = DistributionTest.ReInstall.NEVER)
|
@DistributionTest(reInstall = DistributionTest.ReInstall.NEVER)
|
||||||
@RawDistOnly(reason = "Containers are immutable")
|
@RawDistOnly(reason = "Containers are immutable")
|
||||||
|
@ -44,9 +45,9 @@ public class StartAutoBuildDistTest {
|
||||||
cliResult.assertMessage("Changes detected in configuration. Updating the server image.");
|
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("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("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("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"));
|
assertFalse(cliResult.getOutput().contains("--cache"));
|
||||||
cliResult.assertStarted();
|
cliResult.assertStarted();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
package org.keycloak.it.cli.dist;
|
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.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
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.Launch;
|
||||||
import io.quarkus.test.junit.main.LaunchResult;
|
import io.quarkus.test.junit.main.LaunchResult;
|
||||||
|
import org.keycloak.it.utils.KeycloakDistribution;
|
||||||
|
|
||||||
@DistributionTest
|
@DistributionTest
|
||||||
public class StartCommandDistTest extends StartCommandTest {
|
public class StartCommandDistTest extends StartCommandTest {
|
||||||
|
|
||||||
@Test
|
@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) {
|
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."),
|
CLIResult cliResult = (CLIResult) result;
|
||||||
() -> "The Output:\n" + result.getErrorOutput() + "doesn't contains the expected string.");
|
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, result.getErrorStream().size());
|
assertEquals(4, cliResult.getErrorStream().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -54,9 +57,9 @@ public class StartCommandDistTest extends StartCommandTest {
|
||||||
cliResult.assertMessage("Changes detected in configuration. Updating the server image.");
|
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("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("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("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"));
|
assertFalse(cliResult.getOutput().contains("--cache"));
|
||||||
cliResult.assertStarted();
|
cliResult.assertStarted();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue