From 7f4bb5ce929a819029464a6290c8c642d0b31ccf Mon Sep 17 00:00:00 2001 From: Jochen Schalanda Date: Thu, 26 Nov 2020 17:29:04 +0100 Subject: [PATCH] Add ConfigOverride for random application ports during tests (#3561) 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 EXTENSION = new DropwizardAppExtension<>(MyApplication.class, // no config file null, // adds all necessary config overrides for random ports randomPorts()); ``` Closes #3561 --- .../io/dropwizard/testing/ConfigOverride.java | 36 +++++++------- .../testing/ConfigOverrideRandomPorts.java | 49 +++++++++++++++++++ .../testing/ConfigOverrideValue.java | 33 +++++++++++++ ...xtensionRandomPortsConfigOverrideTest.java | 39 +++++++++++++++ 4 files changed, 138 insertions(+), 19 deletions(-) create mode 100644 dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverrideRandomPorts.java create mode 100644 dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverrideValue.java create mode 100644 dropwizard-testing/src/test/java/io/dropwizard/testing/junit5/DropwizardAppExtensionRandomPortsConfigOverrideTest.java diff --git a/dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverride.java b/dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverride.java index 46cf7c6ad1c..4062c787182 100644 --- a/dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverride.java +++ b/dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverride.java @@ -30,42 +30,40 @@ *
  • ConfigOverride.config("logging.loggers.com\\.example\\.bar", * "DEBUG") will add a logger with the name "com.example.bar" configured * for debug logging.
  • + *
  • ConfigOverride.randomPorts() will change the ports of the + * default applicationConnectors and adminConnectors to 0 so the tests start + * with random ports.
  • * */ -public class ConfigOverride { +public abstract class ConfigOverride { - public static final String DEFAULT_PREFIX = "dw."; - private final String key; - private final Supplier value; - private final String propertyPrefix; - - private ConfigOverride(String propertyPrefix, String key, Supplier 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 value) { - return new ConfigOverride(DEFAULT_PREFIX, key, value); + return new ConfigOverrideValue(DEFAULT_PREFIX, key, value); } public static ConfigOverride config(String propertyPrefix, String key, Supplier 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(); } diff --git a/dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverrideRandomPorts.java b/dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverrideRandomPorts.java new file mode 100644 index 00000000000..b6d9116cc20 --- /dev/null +++ b/dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverrideRandomPorts.java @@ -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); + } + } +} diff --git a/dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverrideValue.java b/dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverrideValue.java new file mode 100644 index 00000000000..355cdc4c566 --- /dev/null +++ b/dropwizard-testing/src/main/java/io/dropwizard/testing/ConfigOverrideValue.java @@ -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 value; + private final String propertyPrefix; + @Nullable + private String originalValue = null; + + ConfigOverrideValue(String propertyPrefix, String key, Supplier 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); + } + } +} diff --git a/dropwizard-testing/src/test/java/io/dropwizard/testing/junit5/DropwizardAppExtensionRandomPortsConfigOverrideTest.java b/dropwizard-testing/src/test/java/io/dropwizard/testing/junit5/DropwizardAppExtensionRandomPortsConfigOverrideTest.java new file mode 100644 index 00000000000..403c7990117 --- /dev/null +++ b/dropwizard-testing/src/test/java/io/dropwizard/testing/junit5/DropwizardAppExtensionRandomPortsConfigOverrideTest.java @@ -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 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); + } +}