Skip to content

Commit

Permalink
Merge pull request quarkusio#15441 from geoand/launcher-ssl-capturing
Browse files Browse the repository at this point in the history
Avoid race condition in determining if SSL is used in integration tests
  • Loading branch information
geoand authored Mar 9, 2021
2 parents 345bf2a + 8f3f46f commit ee25c48
Show file tree
Hide file tree
Showing 13 changed files with 319 additions and 249 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusIntegrationTest;

@Disabled("This test seems flaky")
@QuarkusIntegrationTest
public class GreetingResourceIT {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ public interface ArtifactLauncher extends Closeable {

void addSystemProperties(Map<String, String> systemProps);

boolean isDefaultSsl();
boolean listensOnSsl();
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package io.quarkus.test.common;

import static io.quarkus.test.common.LauncherUtil.installAndGetSomeConfig;
import static io.quarkus.test.common.LauncherUtil.updateConfigForPort;
import static io.quarkus.test.common.LauncherUtil.waitForCapturedListeningData;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -26,11 +28,13 @@ public class DockerContainerLauncher implements ArtifactLauncher {
private final String containerImage;
private final String profile;
private Process quarkusProcess;
private int port;
private final int httpPort;
private final int httpsPort;
private final long jarWaitTime;
private final Map<String, String> systemProps = new HashMap<>();

private boolean isSsl;

private DockerContainerLauncher(String containerImage, Config config) {
this(containerImage,
config.getValue("quarkus.http.test-port", OptionalInt.class).orElse(DEFAULT_PORT),
Expand All @@ -44,9 +48,9 @@ public DockerContainerLauncher(String containerImage) {
this(containerImage, installAndGetSomeConfig());
}

public DockerContainerLauncher(String containerImage, int port, int httpsPort, long jarWaitTime, String profile) {
public DockerContainerLauncher(String containerImage, int httpPort, int httpsPort, long jarWaitTime, String profile) {
this.containerImage = containerImage;
this.port = port;
this.httpPort = httpPort;
this.httpsPort = httpsPort;
this.jarWaitTime = jarWaitTime;
this.profile = profile;
Expand All @@ -61,35 +65,40 @@ public void start() throws IOException {
args.add("run");
args.add("--rm");
args.add("-p");
args.add(port + ":" + port);
args.add(httpPort + ":" + httpPort);
args.add("-p");
args.add(httpsPort + ":" + httpsPort);
args.addAll(toEnvVar("quarkus.http.port", "" + port));
args.addAll(toEnvVar("quarkus.http.port", "" + httpPort));
args.addAll(toEnvVar("quarkus.http.ssl-port", "" + httpsPort));
// this won't be correct when using the random port but it's really only used by us for the rest client tests
// in the main module, since those tests hit the application itself
args.addAll(toEnvVar("test.url", TestHTTPResourceManager.getUri()));
if (profile != null) {
args.addAll(toEnvVar("quarkus.profile", profile));
}

for (Map.Entry<String, String> e : systemProps.entrySet()) {
args.addAll(toEnvVar(e.getKey(), e.getValue()));
}
args.add(containerImage);

Path logFile = PropertyTestUtil.getLogFilePath();
Files.deleteIfExists(logFile);

System.out.println("Executing " + args);

quarkusProcess = Runtime.getRuntime().exec(args.toArray(new String[0]));
port = LauncherUtil.doStart(quarkusProcess, port, httpsPort, jarWaitTime, null);
// the idea here is to obtain the logs of the application simply by redirecting all its output the a file
// this is done in contrast with the JarLauncher and NativeImageLauncher because in the case of the container
// the log itself is written inside the container
quarkusProcess = new ProcessBuilder(args).redirectError(logFile.toFile()).redirectOutput(logFile.toFile()).start();

ListeningAddress result = waitForCapturedListeningData(quarkusProcess, logFile, jarWaitTime);
updateConfigForPort(result.getPort());
isSsl = result.isSsl();
}

public boolean isDefaultSsl() {
try (Socket s = new Socket()) {
s.connect(new InetSocketAddress("localhost", port));
return false;
} catch (IOException e) {
return true;
}
public boolean listensOnSsl() {
return isSsl;
}

public void addSystemProperties(Map<String, String> systemProps) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package io.quarkus.test.common;

import static io.quarkus.test.common.LauncherUtil.installAndGetSomeConfig;
import static io.quarkus.test.common.LauncherUtil.updateConfigForPort;
import static io.quarkus.test.common.LauncherUtil.waitForCapturedListeningData;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -26,11 +27,13 @@ public class JarLauncher implements ArtifactLauncher {
private final Path jarPath;
private final String profile;
private Process quarkusProcess;
private int port;
private final int httpPort;
private final int httpsPort;
private final long jarWaitTime;
private final Map<String, String> systemProps = new HashMap<>();

private boolean isSsl;

private JarLauncher(Path jarPath, Config config) {
this(jarPath,
config.getValue("quarkus.http.test-port", OptionalInt.class).orElse(DEFAULT_PORT),
Expand All @@ -44,9 +47,9 @@ public JarLauncher(Path jarPath) {
this(jarPath, installAndGetSomeConfig());
}

public JarLauncher(Path jarPath, int port, int httpsPort, long jarWaitTime, String profile) {
public JarLauncher(Path jarPath, int httpPort, int httpsPort, long jarWaitTime, String profile) {
this.jarPath = jarPath;
this.port = port;
this.httpPort = httpPort;
this.httpsPort = httpsPort;
this.jarWaitTime = jarWaitTime;
this.profile = profile;
Expand All @@ -58,12 +61,14 @@ public void start() throws IOException {

List<String> args = new ArrayList<>();
args.add("java");
args.add("-Dquarkus.http.port=" + port);
args.add("-Dquarkus.http.port=" + httpPort);
args.add("-Dquarkus.http.ssl-port=" + httpsPort);
// this won't be correct when using the random port but it's really only used by us for the rest client tests
// in the main module, since those tests hit the application itself
args.add("-Dtest.url=" + TestHTTPResourceManager.getUri());
args.add("-Dquarkus.log.file.path=" + PropertyTestUtil.getLogFileLocation());
Path logFile = PropertyTestUtil.getLogFilePath();
args.add("-Dquarkus.log.file.path=" + logFile.toAbsolutePath().toString());
args.add("-Dquarkus.log.file.enable=true");
if (profile != null) {
args.add("-Dquarkus.profile=" + profile);
}
Expand All @@ -75,17 +80,15 @@ public void start() throws IOException {

System.out.println("Executing " + args);

quarkusProcess = Runtime.getRuntime().exec(args.toArray(new String[0]));
port = LauncherUtil.doStart(quarkusProcess, port, httpsPort, jarWaitTime, null);
Files.deleteIfExists(logFile);
quarkusProcess = LauncherUtil.launchProcess(args);
ListeningAddress result = waitForCapturedListeningData(quarkusProcess, logFile, jarWaitTime);
updateConfigForPort(result.getPort());
isSsl = result.isSsl();
}

public boolean isDefaultSsl() {
try (Socket s = new Socket()) {
s.connect(new InetSocketAddress("localhost", port));
return false;
} catch (IOException e) {
return true;
}
public boolean listensOnSsl() {
return isSsl;
}

public void addSystemProperties(Map<String, String> systemProps) {
Expand Down
Loading

0 comments on commit ee25c48

Please sign in to comment.