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 24, 2023
1 parent ae0a481 commit e477102
Show file tree
Hide file tree
Showing 15 changed files with 141 additions and 81 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
@@ -1,32 +1,33 @@
package io.quarkus.test.configuration;

import jakarta.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;

import java.io.InputStream;
import java.time.Duration;
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.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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 +36,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 +49,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 +58,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,11 +96,11 @@ 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);
Expand All @@ -108,19 +109,61 @@ private static Map<String, String> loadPropertiesFrom(String propertiesFile, Str
// There is no properties file: this is not mandatory.
}

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.valueOf(property), (String) entry.getValue());
}
}

return properties;
}

public enum Property {
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"),

PRIVILEGED_MODE("container.privileged-mode"),
REUSABLE_MODE("container.reusable"),
LOG_ENABLE("log.enable"),
LOG_LEVEL_NAME("log.level");

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;
}
}
}
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 = service.getOwner().getConfiguration().get(Configuration.Property.valueOf(propertyKey));
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 = GLOBAL.get(Configuration.Property.valueOf(propertyKey));
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 @@ -17,14 +17,14 @@
import org.hamcrest.Matchers;

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

/**
* Awaitility utils to make a long or repeatable operation.
*/
public final class AwaitilityUtils {

private static final String TIMEOUT_FACTOR_PROPERTY = "factor.timeout";
private static final int POLL_SECONDS = 1;
private static final int TIMEOUT_SECONDS = 30;

Expand Down Expand Up @@ -174,7 +174,8 @@ private static ConditionFactory awaits(AwaitilitySettings settings) {
private static long timeoutInSeconds(AwaitilitySettings settings) {
double timeoutFactor = 1.0;
if (settings.service != null) {
timeoutFactor = settings.service.getConfiguration().getAsDouble(TIMEOUT_FACTOR_PROPERTY, timeoutFactor);
timeoutFactor = settings.service.getConfiguration()
.getAsDouble(Configuration.Property.TIMEOUT_FACTOR_PROPERTY, timeoutFactor);
}

return Math.round(settings.timeout.toSeconds() * timeoutFactor);
Expand Down
Loading

0 comments on commit e477102

Please sign in to comment.