Skip to content

Commit

Permalink
Unification of all test-framework-related options
Browse files Browse the repository at this point in the history
Since all of them are now gathered in one place
it would become easier to monitor and document them
Required for potential automation of quarkus-qe#369
  • Loading branch information
fedinskiy committed May 29, 2023
1 parent ae0a481 commit 37a5005
Show file tree
Hide file tree
Showing 16 changed files with 184 additions and 86 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.quarkus.test.services.containers;

import static io.quarkus.test.bootstrap.BaseService.SERVICE_STARTUP_TIMEOUT;
import static io.quarkus.test.bootstrap.BaseService.SERVICE_STARTUP_TIMEOUT_DEFAULT;
import static io.quarkus.test.utils.PropertiesUtils.RESOURCE_PREFIX;
import static io.quarkus.test.utils.PropertiesUtils.RESOURCE_WITH_DESTINATION_PREFIX;
Expand All @@ -24,14 +23,14 @@
import io.quarkus.test.bootstrap.ManagedResource;
import io.quarkus.test.bootstrap.Protocol;
import io.quarkus.test.bootstrap.ServiceContext;
import io.quarkus.test.configuration.Configuration;
import io.quarkus.test.logging.LoggingHandler;
import io.quarkus.test.logging.TestContainersLoggingHandler;
import io.quarkus.test.services.URILike;
import io.quarkus.test.utils.DockerUtils;

public abstract class DockerContainerManagedResource implements ManagedResource {

private static final String DELETE_IMAGE_ON_STOP_PROPERTY = "container.delete.image.on.stop";
private static final String TARGET = "target";

private final ServiceContext context;
Expand Down Expand Up @@ -59,7 +58,7 @@ public void start() {
}

innerContainer.withStartupTimeout(context.getOwner().getConfiguration()
.getAsDuration(SERVICE_STARTUP_TIMEOUT, SERVICE_STARTUP_TIMEOUT_DEFAULT));
.getAsDuration(Configuration.Property.SERVICE_STARTUP_TIMEOUT, SERVICE_STARTUP_TIMEOUT_DEFAULT));
innerContainer.withEnv(resolveProperties());

loggingHandler = new TestContainersLoggingHandler(context.getOwner(), innerContainer);
Expand All @@ -69,7 +68,7 @@ public void start() {
}

private boolean isDockerImageDeletedOnStop() {
return context.getOwner().getConfiguration().isTrue(DELETE_IMAGE_ON_STOP_PROPERTY);
return context.getOwner().getConfiguration().isTrue(Configuration.Property.DELETE_IMAGE_ON_STOP_PROPERTY);
}

protected abstract GenericContainer<?> initContainer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;

import io.quarkus.test.configuration.Configuration;
import io.quarkus.test.logging.Log;
import io.quarkus.test.utils.DockerUtils;

public class GenericDockerContainerManagedResource extends DockerContainerManagedResource {

private static final String PRIVILEGED_MODE = "container.privileged-mode";
private static final String REUSABLE_MODE = "container.reusable";
private final ContainerManagedResourceBuilder model;

protected GenericDockerContainerManagedResource(ContainerManagedResourceBuilder model) {
Expand Down Expand Up @@ -68,10 +67,10 @@ public void stop() {
}

protected boolean isReusable() {
return model.getContext().getOwner().getConfiguration().isTrue(REUSABLE_MODE);
return model.getContext().getOwner().getConfiguration().isTrue(Configuration.Property.REUSABLE_MODE);
}

private boolean isPrivileged() {
return model.getContext().getOwner().getConfiguration().isTrue(PRIVILEGED_MODE);
return model.getContext().getOwner().getConfiguration().isTrue(Configuration.Property.PRIVILEGED_MODE);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.test.bootstrap;

import static io.quarkus.test.configuration.Configuration.Property.SERVICE_STARTUP_CHECK_POLL_INTERVAL;
import static io.quarkus.test.utils.AwaitilityUtils.AwaitilitySettings;
import static io.quarkus.test.utils.AwaitilityUtils.untilIsTrue;
import static org.junit.jupiter.api.Assertions.fail;
Expand Down Expand Up @@ -27,11 +28,7 @@

public class BaseService<T extends Service> implements Service {

public static final String SERVICE_STARTUP_TIMEOUT = "startup.timeout";
public static final Duration SERVICE_STARTUP_TIMEOUT_DEFAULT = Duration.ofMinutes(5);
public static final String DELETE_FOLDER_ON_EXIT = "delete.folder.on.exit";

private static final String SERVICE_STARTUP_CHECK_POLL_INTERVAL = "startup.check-poll-interval";
private static final Duration SERVICE_STARTUP_CHECK_POLL_INTERVAL_DEFAULT = Duration.ofSeconds(2);

protected ServiceContext context;
Expand Down Expand Up @@ -224,7 +221,7 @@ public void stop() {
public void close() {
if (!context.getScenarioContext().isDebug()) {
stop();
if (getConfiguration().isTrue(DELETE_FOLDER_ON_EXIT)) {
if (getConfiguration().isTrue(Configuration.Property.DELETE_FOLDER_ON_EXIT)) {
try {
FileUtils.deletePath(getServiceFolder());
} catch (Exception ex) {
Expand Down Expand Up @@ -296,7 +293,7 @@ private void waitUntilServiceIsStarted() {
Duration startupCheckInterval = getConfiguration()
.getAsDuration(SERVICE_STARTUP_CHECK_POLL_INTERVAL, SERVICE_STARTUP_CHECK_POLL_INTERVAL_DEFAULT);
Duration startupTimeout = getConfiguration()
.getAsDuration(SERVICE_STARTUP_TIMEOUT, SERVICE_STARTUP_TIMEOUT_DEFAULT);
.getAsDuration(Configuration.Property.SERVICE_STARTUP_TIMEOUT, SERVICE_STARTUP_TIMEOUT_DEFAULT);
untilIsTrue(this::isRunningOrFailed, AwaitilitySettings
.using(startupCheckInterval, startupTimeout)
.doNotIgnoreExceptions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,36 @@

import java.io.InputStream;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import jakarta.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;

public final class Configuration {

private static final String GLOBAL_PROPERTIES = System.getProperty("ts.test.resources.file.location", "global.properties");
private static final String TEST_PROPERTIES = "test.properties";
private static final String PREFIX_TEMPLATE = "ts.%s.";
private static final String PREFIX = "ts.";
private static final String PREFIX_TEMPLATE = PREFIX + "%s.";
private static final String GLOBAL_SCOPE = "global";

private final Map<String, String> properties;
private final EnumMap<Property, String> properties;

private Configuration(Map<String, String> properties) {
private Configuration(EnumMap<Property, String> properties) {
this.properties = properties;
}

public List<String> getAsList(String property) {
public List<String> getAsList(Property property) {
String value = get(property);
if (StringUtils.isEmpty(value)) {
return Collections.emptyList();
Expand All @@ -35,7 +40,7 @@ public List<String> getAsList(String property) {
return Stream.of(value.split(",")).collect(Collectors.toList());
}

public Duration getAsDuration(String property, Duration defaultValue) {
public Duration getAsDuration(Property property, Duration defaultValue) {
String value = get(property);
if (StringUtils.isEmpty(value)) {
return defaultValue;
Expand All @@ -48,7 +53,7 @@ public Duration getAsDuration(String property, Duration defaultValue) {
return Duration.parse(value);
}

public Double getAsDouble(String property, double defaultValue) {
public Double getAsDouble(Property property, double defaultValue) {
String value = get(property);
if (StringUtils.isEmpty(value)) {
return defaultValue;
Expand All @@ -57,24 +62,24 @@ public Double getAsDouble(String property, double defaultValue) {
return Double.parseDouble(value);
}

public String get(String property) {
public String get(Property property) {
return properties.get(property);
}

public String getOrDefault(String property, String defaultValue) {
public String getOrDefault(Property property, String defaultValue) {
return properties.getOrDefault(property, defaultValue);
}

public boolean isTrue(String property) {
public boolean isTrue(Property property) {
return is(property, Boolean.TRUE.toString());
}

public boolean is(String property, String expected) {
public boolean is(Property property, String expected) {
return StringUtils.equalsIgnoreCase(properties.get(property), expected);
}

public static Configuration load() {
Map<String, String> properties = new HashMap<>();
EnumMap<Property, String> properties = new EnumMap<>(Property.class);
// Lowest priority: properties from global.properties and scope `global`
properties.putAll(loadPropertiesFrom(GLOBAL_PROPERTIES, GLOBAL_SCOPE));
// Then, properties from system properties and scope `global`
Expand All @@ -95,32 +100,108 @@ public static Configuration load(String serviceName) {
return configuration;
}

private static Map<String, String> loadPropertiesFromSystemProperties(String scope) {
private static EnumMap<Property, String> loadPropertiesFromSystemProperties(String scope) {
return loadPropertiesFrom(System.getProperties(), scope);
}

private static Map<String, String> loadPropertiesFrom(String propertiesFile, String scope) {
private static EnumMap<Property, String> loadPropertiesFrom(String propertiesFile, String scope) {
try (InputStream input = Configuration.class.getClassLoader().getResourceAsStream(propertiesFile)) {
Properties prop = new Properties();
prop.load(input);
return loadPropertiesFrom(prop, scope);
} catch (Exception ignored) {
// There is no properties file: this is not mandatory.
} catch (Exception exception) {
if (exception instanceof NullPointerException && exception.getMessage().equals("inStream parameter is null")) {
System.out.println("No properties file: " + propertiesFile);
} else {
throw new IllegalStateException(exception);
}
}

return Collections.emptyMap();
return new EnumMap<>(Property.class);
}

private static Map<String, String> loadPropertiesFrom(Properties prop, String scope) {
Map<String, String> properties = new HashMap<>();
private static EnumMap<Property, String> loadPropertiesFrom(Properties prop, String scope) {
EnumMap<Property, String> properties = new EnumMap<>(Property.class);

String prefix = String.format(PREFIX_TEMPLATE, scope);
for (Entry<Object, Object> entry : prop.entrySet()) {
String key = (String) entry.getKey();
if (StringUtils.startsWith(key, prefix)) {
properties.put(key.replace(prefix, StringUtils.EMPTY), (String) entry.getValue());
String property = key.replace(prefix, StringUtils.EMPTY);
properties.put(Property.byName(property), (String) entry.getValue());
}
}

return properties;
}

public enum Property { //todo search for uses
RESOURCES_FILE_LOCATION("resources.file.location"),
SERVICE_STARTUP_TIMEOUT("startup.timeout"),
DELETE_FOLDER_ON_EXIT("delete.folder.on.exit"),
SERVICE_STARTUP_CHECK_POLL_INTERVAL("startup.check-poll-interval"),
TIMEOUT_FACTOR_PROPERTY("factor.timeout"),
KUBERNETES_DEPLOYMENT_SERVICE_PROPERTY("kubernetes.service"),
KUBERNETES_DEPLOYMENT_TEMPLATE_PROPERTY("kubernetes.template"),
KUBERNETES_USE_INTERNAL_SERVICE_AS_URL_PROPERTY("kubernetes.use-internal-service-as-url"),
OPENSHIFT_DEPLOYMENT_SERVICE_PROPERTY("openshift.service"),
OPENSHIFT_DEPLOYMENT_TEMPLATE_PROPERTY("openshift.template"),
OPENSHIFT_USE_INTERNAL_SERVICE_AS_URL_PROPERTY("openshift.use-internal-service-as-url"),

DELETE_IMAGE_ON_STOP_PROPERTY("container.delete.image.on.stop"),
IMAGE_STREAM_TIMEOUT("imagestream.install.timeout"),
OPERATOR_INSTALL_TIMEOUT("operator.install.timeout"),

CREATE_SERVICE_BY_DEFAULT("generated-service.enabled"),
PROPAGATE_PROPERTIES_STRATEGY("maven.propagate-properties-strategy"),
PROPAGATE_PROPERTIES_STRATEGY_ALL_EXCLUSIONS("maven.propagate-properties-strategy.all.exclude"),
PRIVILEGED_MODE("container.privileged-mode"),
REUSABLE_MODE("container.reusable"),
EXPECTED_OUTPUT("quarkus.expected.log"),
PORT_RANGE_MIN("port.range.min"),
PORT_RANGE_MAX("port.range.max"),
PORT_RESOLUTION_STRATEGY("port.resolution.strategy"),

METRICS_EXTENSION_ENABLED_PROPERTY("metrics.enabled"),
METRICS_PUSH_AFTER_EACH_TEST("metrics.push-after-each-test"),
METRICS_EXPORT_PROMETHEUS_PROPERTY("metrics.export.prometheus.endpoint"),
JAEGER_HTTP_ENDPOINT_SYSTEM_PROPERTY("tracing.jaeger.endpoint"),

LOG_ENABLE("log.enable"),
LOG_LEVEL_NAME("log.level"),
LOG_FORMAT("log.format"),
LOG_FILE_OUTPUT("log.file.output"),
LOG_NOCOLOR("log.nocolor");

private final String name;

Property(String name) {
this.name = name;
}

public String getName(@Nullable String scope) {
String scopePart = "";
if (scope != null) {
scopePart = scope + ".";
}
return PREFIX + scopePart + name;
}

public String getName() {
return name;
}

public static Optional<Property> getByName(String requested) {
return Arrays.stream(Property.values())
.filter(property -> property.name.equals(requested))
.findAny();
}

static Property byName(String requested) {
return getByName(requested).orElseThrow(() -> new NoSuchElementException("Unknown property: " + requested));
}

public static boolean isKnownProperty(String toCheck) {
return Arrays.stream(Property.values()).map(property -> property.name).anyMatch(name -> name.equals(toCheck));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public String get(ServiceContext service) {
}

// Or from test.properties
value = service.getOwner().getConfiguration().get(propertyKey);
value = Configuration.Property.getByName(propertyKey).map(GLOBAL::get).orElse("");
if (StringUtils.isNotBlank(value)) {
return value;
}
Expand All @@ -50,7 +50,7 @@ public String get(ServiceContext service) {

public String get() {
// Try first using the Configuration API
String value = GLOBAL.get(propertyKey);
String value = Configuration.Property.getByName(propertyKey).map(GLOBAL::get).orElse("");
if (StringUtils.isNotBlank(value)) {
return value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import io.quarkus.test.bootstrap.QuarkusScenarioBootstrap;
import io.quarkus.test.bootstrap.ScenarioContext;
import io.quarkus.test.bootstrap.Service;
import io.quarkus.test.configuration.Configuration;
import io.quarkus.test.configuration.PropertyLookup;

public final class Log {
Expand All @@ -32,7 +33,6 @@ public final class Log {
public static final PropertyLookup LOG_NOCOLOR = new PropertyLookup("log.nocolor", "false");

public static final String LOG_SUFFIX = ".log";
public static final String LOG_LEVEL_NAME = "log.level";

private static final Service NO_SERVICE = null;
private static final String COLOR_RESET = "\u001b[0m";
Expand Down Expand Up @@ -142,7 +142,7 @@ private static void log(Service service, Level level, String msg, Object... args
private static boolean isServiceLogLevelAllowed(Service service, Level level) {
boolean enabled = true;
if (Objects.nonNull(service) && Objects.nonNull(service.getConfiguration())) {
String serviceLogLevel = service.getConfiguration().getOrDefault(LOG_LEVEL_NAME, EMPTY);
String serviceLogLevel = service.getConfiguration().getOrDefault(Configuration.Property.LOG_LEVEL_NAME, EMPTY);
if (!serviceLogLevel.isEmpty()) {
enabled = Level.parse(serviceLogLevel).intValue() <= level.intValue();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.test.logging;

import io.quarkus.test.bootstrap.Service;
import io.quarkus.test.configuration.Configuration;

public abstract class ServiceLoggingHandler extends LoggingHandler {

Expand All @@ -17,7 +18,7 @@ protected void logInfo(String line) {

@Override
protected boolean isLogEnabled() {
return service.getConfiguration().isTrue("log.enable");
return service.getConfiguration().isTrue(Configuration.Property.LOG_ENABLE);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@

public class MetricsExtensionBootstrap implements ExtensionBootstrap {

private static final PropertyLookup METRICS_EXTENSION_ENABLED_PROPERTY = new PropertyLookup(
"metrics.enabled", "true");
private static final PropertyLookup METRICS_PUSH_AFTER_EACH_TEST = new PropertyLookup(
"metrics.push-after-each-test", "false");
private static final PropertyLookup METRICS_EXTENSION_ENABLED_PROPERTY = new PropertyLookup("metrics.enabled",
"true");
private static final PropertyLookup METRICS_PUSH_AFTER_EACH_TEST = new PropertyLookup("metrics.push-after-each-test",
"false");

private final boolean extensionEnabled;

Expand Down
Loading

0 comments on commit 37a5005

Please sign in to comment.