Skip to content

Commit

Permalink
Simplify code in RestAssuredURLManager
Browse files Browse the repository at this point in the history
The code still works whether RestAssured is on the classpath
or not, but it now contains direct invocations of RestAssured
code instead of reflection.
It goes without saying that this make the class a lot more
maintainable

At some point in the future, we probably want to have some
sort of SPI, but for now, this change is much better than the
current state.
  • Loading branch information
geoand committed Jun 28, 2024
1 parent a097216 commit be7d0e7
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 179 deletions.
5 changes: 5 additions & 0 deletions test-framework/common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
<groupId>org.jboss.logging</groupId>
<artifactId>commons-logging-jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package io.quarkus.test.common;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.Optional;

import org.eclipse.microprofile.config.ConfigProvider;

import io.restassured.RestAssured;
import io.restassured.config.HttpClientConfig;
import io.restassured.config.RestAssuredConfig;

/**
* Utility class that sets the rest assured port to the default test port and meaningful timeouts.
* <p>
* This uses reflection so as to not introduce a dependency on rest-assured
* This class works whether RestAssured is on the classpath or not - if it is not, invoking the methods of the class are
* essentially NO-OPs
* <p>
* TODO: do we actually want this here, or should it be in a different module?
*/
Expand All @@ -19,70 +22,21 @@ public class RestAssuredURLManager {
private static final int DEFAULT_HTTP_PORT = 8081;
private static final int DEFAULT_HTTPS_PORT = 8444;

private static final Field portField;
private static final Field baseURIField;
private static final Field basePathField;
private static final Field configField;

private static final Method setParamMethod;
private static final Method configMethod;
private static final Method httpClientMethod;
private static final Class<?> httpClientConfigClass;

private static int oldPort;
private static String oldBaseURI;
private static String oldBasePath;
private static Object oldRestAssuredConfig; // we can't declare the type here as that would prevent this class for being loaded if RestAssured is not present

private static final boolean REST_ASSURED_PRESENT;

static {
Field p;
Field baseURI;
Field basePath;
Field configF;
Method setParam;
Method configM;
Method httpClient;
Class<?> httpClientConfig;
boolean present = false;
try {
Class<?> restAssured = Class.forName("io.restassured.RestAssured");
p = restAssured.getField("port");
p.setAccessible(true);
baseURI = restAssured.getField("baseURI");
baseURI.setAccessible(true);
basePath = restAssured.getField("basePath");
basePath.setAccessible(true);

configF = restAssured.getField("config");
configF.setAccessible(true);

configM = restAssured.getMethod("config");
configM.setAccessible(true);

httpClientConfig = Class.forName("io.restassured.config.HttpClientConfig");
setParam = httpClientConfig.getMethod("setParam", String.class, Object.class);
setParam.setAccessible(true);

Class<?> restAssuredConfigClass = Class.forName("io.restassured.config.RestAssuredConfig");
httpClient = restAssuredConfigClass.getMethod("httpClient", httpClientConfig);
httpClient.setAccessible(true);

} catch (Exception e) {
p = null;
baseURI = null;
basePath = null;
configF = null;
setParam = null;
httpClientConfig = null;
configM = null;
httpClient = null;
Class.forName("io.restassured.RestAssured");
present = true;
} catch (ClassNotFoundException ignored) {
}
portField = p;
baseURIField = baseURI;
basePathField = basePath;
configField = configF;
setParamMethod = setParam;
httpClientConfigClass = httpClientConfig;
configMethod = configM;
httpClientMethod = httpClient;
REST_ASSURED_PRESENT = present;
}

private RestAssuredURLManager() {
Expand Down Expand Up @@ -111,136 +65,76 @@ public static void setURL(boolean useSecureConnection, Integer port) {
}

public static void setURL(boolean useSecureConnection, Integer port, String additionalPath) {
if (portField != null) {
try {
oldPort = (Integer) portField.get(null);
if (port == null) {
port = useSecureConnection ? getPortFromConfig(DEFAULT_HTTPS_PORT, "quarkus.http.test-ssl-port")
: getPortFromConfig(DEFAULT_HTTP_PORT, "quarkus.lambda.mock-event-server.test-port",
"quarkus.http.test-port");
}
portField.set(null, port);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (!REST_ASSURED_PRESENT) {
return;
}
if (baseURIField != null) {
try {
oldBaseURI = (String) baseURIField.get(null);
final String protocol = useSecureConnection ? "https://" : "http://";
String host = ConfigProvider.getConfig().getOptionalValue("quarkus.http.host", String.class)
.orElse("localhost");
if (host.equals("0.0.0.0")) {
host = "localhost";
}
String baseURI = protocol + host;
baseURIField.set(null, baseURI);
} catch (IllegalAccessException e) {
e.printStackTrace();
}

oldPort = RestAssured.port;
if (port == null) {
port = useSecureConnection ? getPortFromConfig(DEFAULT_HTTPS_PORT, "quarkus.http.test-ssl-port")
: getPortFromConfig(DEFAULT_HTTP_PORT, "quarkus.lambda.mock-event-server.test-port",
"quarkus.http.test-port");
}
if (basePathField != null) {
try {
oldBasePath = (String) basePathField.get(null);
Optional<String> basePath = ConfigProvider.getConfig().getOptionalValue("quarkus.http.root-path",
String.class);
if (basePath.isPresent() || additionalPath != null) {
StringBuilder bp = new StringBuilder();
if (basePath.isPresent()) {
if (basePath.get().startsWith("/")) {
bp.append(basePath.get().substring(1));
} else {
bp.append(basePath.get());
}
if (bp.toString().endsWith("/")) {
bp.setLength(bp.length() - 1);
}
}
if (additionalPath != null) {
if (!additionalPath.startsWith("/")) {
bp.append("/");
}
bp.append(additionalPath);
if (bp.toString().endsWith("/")) {
bp.setLength(bp.length() - 1);
}
}
basePathField.set(null, bp.toString());
RestAssured.port = port;

oldBaseURI = RestAssured.baseURI;
final String protocol = useSecureConnection ? "https://" : "http://";
String host = ConfigProvider.getConfig().getOptionalValue("quarkus.http.host", String.class)
.orElse("localhost");
if (host.equals("0.0.0.0")) {
host = "localhost";
}
RestAssured.baseURI = protocol + host;

oldBasePath = RestAssured.basePath;
Optional<String> basePath = ConfigProvider.getConfig().getOptionalValue("quarkus.http.root-path",
String.class);
if (basePath.isPresent() || additionalPath != null) {
StringBuilder bp = new StringBuilder();
if (basePath.isPresent()) {
if (basePath.get().startsWith("/")) {
bp.append(basePath.get().substring(1));
} else {
bp.append(basePath.get());
}
if (bp.toString().endsWith("/")) {
bp.setLength(bp.length() - 1);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if (configField != null) {
try {
Duration timeout = ConfigProvider.getConfig()
.getOptionalValue("quarkus.http.test-timeout", Duration.class).orElse(Duration.ofSeconds(30));
configureTimeouts(timeout);
} catch (Exception e) {
e.printStackTrace();
if (additionalPath != null) {
if (!additionalPath.startsWith("/")) {
bp.append("/");
}
bp.append(additionalPath);
if (bp.toString().endsWith("/")) {
bp.setLength(bp.length() - 1);
}
}
RestAssured.basePath = bp.toString();
}

Duration timeout = ConfigProvider.getConfig()
.getOptionalValue("quarkus.http.test-timeout", Duration.class).orElse(Duration.ofSeconds(30));
configureTimeouts(timeout);
}

/**
* Execute the following code:
*
* <pre>
* {@code
* RestAssured.config = RestAssured.config().httpClient(
* new HttpClientConfig()
* .setParam("http.conn-manager.timeout", 30_000L)
* .setParam("http.connection.timeout", 30_000)
* .setParam("http.socket.timeout", 30_000)
* }
* </pre>
*
*/
private static void configureTimeouts(Duration d) throws Exception {
// Create the HTTP client config:
// new HttpClientConfig()
// .setParam("http.conn-manager.timeout", 30_000L)
// .setParam("http.connection.timeout", 30_000)
// .setParam("http.socket.timeout", 30_000)

Object httpClientConfig = httpClientConfigClass.getDeclaredConstructor().newInstance();
httpClientConfig = setParamMethod.invoke(httpClientConfig, "http.conn-manager.timeout", d.toMillis());
httpClientConfig = setParamMethod.invoke(httpClientConfig, "http.connection.timeout", (int) d.toMillis());
httpClientConfig = setParamMethod.invoke(httpClientConfig, "http.socket.timeout", (int) d.toMillis());

// Retrieve RestAssured config
// restAssuredConfig = RestAssured.config();
Object restAssuredConfig = configMethod.invoke(null);

// Call httpClient method:
// restAssuredConfig = restAssuredConfig.httpClient(httpClientConfig);
restAssuredConfig = httpClientMethod.invoke(restAssuredConfig, httpClientConfig);

// Set the field
configField.set(null, restAssuredConfig);
private static void configureTimeouts(Duration d) {
oldRestAssuredConfig = RestAssured.config();

RestAssured.config = RestAssured.config().httpClient(new HttpClientConfig()
.setParam("http.conn-manager.timeout", d.toMillis()) // this needs to be long
.setParam("http.connection.timeout", (int) d.toMillis()) // this needs to be int
.setParam("http.socket.timeout", (int) d.toMillis())); // same here
}

public static void clearURL() {
if (portField != null) {
try {
portField.set(null, oldPort);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if (baseURIField != null) {
try {
baseURIField.set(null, oldBaseURI);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if (basePathField != null) {
try {
basePathField.set(null, oldBasePath);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (!REST_ASSURED_PRESENT) {
return;
}

RestAssured.port = oldPort;
RestAssured.baseURI = oldBaseURI;
RestAssured.basePath = oldBasePath;
RestAssured.config = (RestAssuredConfig) oldRestAssuredConfig;
}
}

0 comments on commit be7d0e7

Please sign in to comment.