Skip to content

Commit

Permalink
Add ConfigOverride for random application ports during tests (#3561)
Browse files Browse the repository at this point in the history
Problem:

We are doing a lot of integration testing where we need to start the application. We primarily use the config overrides instead of a `test-config.yaml` to do the configuration. Our config files of the test module often only contain the configuration for the random ports:
```yaml
server:
  applicationConnectors:
    - type: http
      port: 0
  adminConnectors:
    - type: http
      port: 0
```

It would be nice to be able to use random ports with the `DropwizardAppRule`/`DropwizardAppExtension` programmatically.

Solution:

Add a Config Override that configures the default application and admin connectors to use port `0`.

```java
private static final DropwizardAppExtension<MyConfiguration> EXTENSION =
    new DropwizardAppExtension<>(MyApplication.class,
        // no config file
        null,
        // adds all necessary config overrides for random ports
        randomPorts());
```

Closes #3561

(cherry picked from commit 7f4bb5c)
  • Loading branch information
joschi committed Nov 26, 2020
1 parent 2a9e710 commit 13177e4
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 19 deletions.
Expand Up @@ -30,42 +30,40 @@
* <li><code>ConfigOverride.config("logging.loggers.com\\.example\\.bar",
* "DEBUG")</code> will add a logger with the name "com.example.bar" configured
* for debug logging.</li>
* <li><code>ConfigOverride.randomPorts()</code> will change the ports of the
* default applicationConnectors and adminConnectors to 0 so the tests start
* with random ports.</li>
* </ul>
*/
public class ConfigOverride {
public abstract class ConfigOverride {

public static final String DEFAULT_PREFIX = "dw.";
private final String key;
private final Supplier<String> value;
private final String propertyPrefix;

private ConfigOverride(String propertyPrefix, String key, Supplier<String> value) {
this.key = key;
this.value = value;
this.propertyPrefix = propertyPrefix.endsWith(".") ? propertyPrefix : propertyPrefix + ".";
}
static final String DEFAULT_PREFIX = "dw.";

public static ConfigOverride config(String key, String value) {
return new ConfigOverride(DEFAULT_PREFIX, key, () -> value);
return new ConfigOverrideValue(DEFAULT_PREFIX, key, () -> value);
}

public static ConfigOverride config(String propertyPrefix, String key, String value) {
return new ConfigOverride(propertyPrefix, key, () -> value);
return new ConfigOverrideValue(propertyPrefix, key, () -> value);
}

public static ConfigOverride config(String key, Supplier<String> value) {
return new ConfigOverride(DEFAULT_PREFIX, key, value);
return new ConfigOverrideValue(DEFAULT_PREFIX, key, value);
}

public static ConfigOverride config(String propertyPrefix, String key, Supplier<String> value) {
return new ConfigOverride(propertyPrefix, key, value);
return new ConfigOverrideValue(propertyPrefix, key, value);
}

public void addToSystemProperties() {
System.setProperty(propertyPrefix + key, value.get());
public static ConfigOverride randomPorts() {
return new ConfigOverrideRandomPorts(DEFAULT_PREFIX);
}

public void removeFromSystemProperties() {
System.clearProperty(propertyPrefix + key);
public static ConfigOverride randomPorts(String propertyPrefix) {
return new ConfigOverrideRandomPorts(propertyPrefix);
}

public abstract void addToSystemProperties();

public abstract void removeFromSystemProperties();
}
@@ -0,0 +1,49 @@
package io.dropwizard.testing;

import javax.annotation.Nullable;

/**
* Override port configuration setting for application and admin connectors and choose a random port.
*
* @see io.dropwizard.jetty.HttpConnectorFactory#getPort()
* @see io.dropwizard.Configuration#getServerFactory()
* @see io.dropwizard.server.DefaultServerFactory#getApplicationConnectors()
* @see io.dropwizard.server.DefaultServerFactory#getAdminConnectors()
*/
public class ConfigOverrideRandomPorts extends ConfigOverride {

private static final String SERVER_APPLICATION_CONNECTORS_PORT = "server.applicationConnectors[0].port";
private static final String SERVER_ADMIN_CONNECTORS_PORT = "server.adminConnectors[0].port";

private final String propertyPrefix;

@Nullable
private String applicationConnectorsPort = null;
@Nullable
private String adminConnectorsPort = null;

ConfigOverrideRandomPorts(String propertyPrefix) {
this.propertyPrefix = propertyPrefix.endsWith(".") ? propertyPrefix : propertyPrefix + ".";
}

@Override
public void addToSystemProperties() {
applicationConnectorsPort = System.setProperty(propertyPrefix + SERVER_APPLICATION_CONNECTORS_PORT, "0");
adminConnectorsPort = System.setProperty(propertyPrefix + SERVER_ADMIN_CONNECTORS_PORT, "0");
}

@Override
public void removeFromSystemProperties() {
if (applicationConnectorsPort != null) {
System.setProperty(propertyPrefix + SERVER_APPLICATION_CONNECTORS_PORT, applicationConnectorsPort);
} else {
System.clearProperty(propertyPrefix + SERVER_APPLICATION_CONNECTORS_PORT);
}

if (adminConnectorsPort != null) {
System.setProperty(propertyPrefix + SERVER_ADMIN_CONNECTORS_PORT, adminConnectorsPort);
} else {
System.clearProperty(propertyPrefix + SERVER_ADMIN_CONNECTORS_PORT);
}
}
}
@@ -0,0 +1,33 @@
package io.dropwizard.testing;

import javax.annotation.Nullable;
import java.util.function.Supplier;

public class ConfigOverrideValue extends ConfigOverride {

private final String key;
private final Supplier<String> value;
private final String propertyPrefix;
@Nullable
private String originalValue = null;

ConfigOverrideValue(String propertyPrefix, String key, Supplier<String> value) {
this.key = key;
this.value = value;
this.propertyPrefix = propertyPrefix.endsWith(".") ? propertyPrefix : propertyPrefix + ".";
}

@Override
public void addToSystemProperties() {
this.originalValue = System.setProperty(propertyPrefix + key, value.get());
}

@Override
public void removeFromSystemProperties() {
if (originalValue != null) {
System.setProperty(propertyPrefix + key, originalValue);
} else {
System.clearProperty(propertyPrefix + key);
}
}
}
@@ -0,0 +1,39 @@
package io.dropwizard.testing.junit5;

import static io.dropwizard.testing.ConfigOverride.config;
import static io.dropwizard.testing.ConfigOverride.randomPorts;
import static org.assertj.core.api.Assertions.assertThat;

import io.dropwizard.jetty.HttpConnectorFactory;
import io.dropwizard.server.DefaultServerFactory;
import io.dropwizard.testing.app.TestApplication;
import io.dropwizard.testing.app.TestConfiguration;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(DropwizardExtensionsSupport.class)
class DropwizardAppExtensionRandomPortsConfigOverrideTest {

private static final DropwizardAppExtension<TestConfiguration> EXTENSION =
new DropwizardAppExtension<>(TestApplication.class,
null,
"app-rule",
randomPorts("app-rule"),
config("app-rule", "message", "A new way to say Hooray!"),
config("app-rule", "extra", () -> "supplied"));

@Test
void supportsRandomPortsConfigAttributeOverrides() {
DefaultServerFactory serverFactory = (DefaultServerFactory) EXTENSION.getConfiguration()
.getServerFactory();

assertThat(
serverFactory.getApplicationConnectors().stream().map(HttpConnectorFactory.class::cast))
.extracting(
HttpConnectorFactory::getPort).containsExactly(0);
assertThat(
serverFactory.getAdminConnectors().stream().map(HttpConnectorFactory.class::cast))
.extracting(
HttpConnectorFactory::getPort).containsExactly(0);
}
}

0 comments on commit 13177e4

Please sign in to comment.