Skip to content

Commit

Permalink
Merge branch '2.5.x' into 2.6.x
Browse files Browse the repository at this point in the history
  • Loading branch information
melix committed May 14, 2024
2 parents 17592c0 + 73f268c commit 785d9b7
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 16 deletions.
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
# a managed version (a version which alias starts with "managed-"

[versions]
micronaut = "4.4.1"
micronaut-platform = "4.3.7"
micronaut = "4.4.2"
micronaut-platform = "4.4.2"
micronaut-aot = "2.4.0"
micronaut-aws = "4.5.0"
micronaut-control-panel = "1.3.0"
Expand Down
6 changes: 6 additions & 0 deletions src/main/docs/guide/architecture-configuration.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
=== Docker Client creation timeout

The test-resources server communicates with Docker via a docker client.
By default, creation of this client is expected to take less than 10 seconds.
However, under certain circumstances (limited resources, docker in docker, etc.), this may take longer.
To configure the timeout, you can pass a system property `docker.check.timeout.seconds` or an environment variable `TEST_RESOURCES_DOCKER_CHECK_TIMEOUT_SECONDS` with the number of seconds you require.
1 change: 1 addition & 0 deletions src/main/docs/guide/architecture-server.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ For example, a MySQL database may need to be started when the tests start, and s
For this purpose, the test resource server must be started before the application under test starts, and shutdown after test resources are no longer needed.

It means, for example, that with https://docs.gradle.org/current/userguide/userguide_single.html#sec:continuous_build[Gradle continuous builds], the test resources server would outlive a single build, making it possible to develop your application while not paying the price of starting a container on each build.

3 changes: 3 additions & 0 deletions src/main/docs/guide/modules-opensearch.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
OpenSearch support will automatically start an https://opensearch.org/[OpenSearch] container and provide the value of the `micronaut.opensearch.rest-client.http-hosts` or `micronaut.opensearch.httpclient5.http-hosts` properties.

The default image (`opensearchproject/opensearch:latest`) can be overwritten by setting the `test-resources.containers.opensearch.image-name` property.
4 changes: 4 additions & 0 deletions src/main/docs/guide/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ modules:
title: R2DBC
modules-elasticsearch:
title: Elasticsearch
modules-opensearch:
title: OpenSearch
modules-kafka:
title: Kafka
modules-localstack:
Expand Down Expand Up @@ -49,6 +51,8 @@ architecture:
title: The test resources server
architecture-shared-server:
title: Sharing containers between independent builds
architecture-configuration:
title: Configuring the server
architecture-client:
title: The test resources client
architecture-embedded:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ public class ServerUtils {
private static final String CDS_CLASS_LST = "cds.classlist";
private static final String FLAT_JAR = "flat.jar";

// See io.micronaut.testresources.testcontainers.DockerSupport.TIMEOUT
private static final String DOCKER_CHECK_TIMEOUT_SECONDS_ENV = "TEST_RESOURCES_DOCKER_CHECK_TIMEOUT_SECONDS";
private static final String DOCKER_CHECK_TIMEOUT_SECONDS_PROPERTY = "docker.check.timeout.seconds";

/**
* Writes the server settings in an output directory.
*
Expand Down Expand Up @@ -461,6 +465,13 @@ public boolean isCDSDumpInvocation() {
public Map<String, String> getSystemProperties() {
Map<String, String> systemProperties = new HashMap<>();
systemProperties.put(JMX_SYSTEM_PROPERTY, null);
String dockerCheckTimeout = System.getProperty(DOCKER_CHECK_TIMEOUT_SECONDS_PROPERTY);
if (dockerCheckTimeout == null) {
dockerCheckTimeout = System.getenv(DOCKER_CHECK_TIMEOUT_SECONDS_ENV);
}
if (dockerCheckTimeout != null) {
systemProperties.put(DOCKER_CHECK_TIMEOUT_SECONDS_PROPERTY, dockerCheckTimeout);
}
if (explicitPort != null) {
systemProperties.put(MICRONAUT_SERVER_PORT, String.valueOf(explicitPort));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,23 @@ class ServerUtilsTest extends Specification {
'abc' | [new File('def')] | 98
}

@RestoreSystemProperties
def "can set the docker check timeout"() {
def portFile = tmpDir.resolve("port-file")
def settingsDir = tmpDir.resolve("settings")
def factory = Mock(ServerFactory)
System.setProperty('docker.check.timeout.seconds', "100")

when:
ServerUtils.startOrConnectToExistingServer(9999, portFile, settingsDir, null, null, null, null, factory)

then:
1 * factory.startServer(_) >> { ServerUtils.ProcessParameters params ->
assert params.mainClass == 'io.micronaut.testresources.server.TestResourcesService'
assert params.systemProperties['docker.check.timeout.seconds'] == '100'
}
}

@RestoreSystemProperties
def "waits for the server to be available when using an explicit port"() {
def portFile = tmpDir.resolve("port-file")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,18 @@
*/
@Internal
public final class TestResourcesClientHolder {
private static TestResourcesClient CLIENT;
private static TestResourcesClient client;

private TestResourcesClientHolder() {

}

public static void set(TestResourcesClient client) {
CLIENT = client;
TestResourcesClientHolder.client = client;
}

public static TestResourcesClient get() {
return CLIENT;
return client;
}

public static TestResourcesClient lazy() {
Expand All @@ -51,45 +51,45 @@ public static TestResourcesClient lazy() {
private static class LazyTestResourcesClient implements TestResourcesClient {

private static <T> T nullSafe(Supplier<T> value) {
if (CLIENT == null) {
if (client == null) {
return null;
}
return value.get();
}

@Override
public List<String> getResolvableProperties(Map<String, Collection<String>> propertyEntries, Map<String, Object> testResourcesConfig) {
return nullSafe(CLIENT::getResolvableProperties);
return nullSafe(client::getResolvableProperties);
}

@Override
public Optional<String> resolve(String name, Map<String, Object> properties, Map<String, Object> testResourcesConfig) {
return nullSafe(() -> CLIENT.resolve(name, properties, testResourcesConfig));
return nullSafe(() -> client.resolve(name, properties, testResourcesConfig));
}

@Override
public List<String> getRequiredProperties(String expression) {
return nullSafe(() -> CLIENT.getRequiredProperties(expression));
return nullSafe(() -> client.getRequiredProperties(expression));
}

@Override
public List<String> getRequiredPropertyEntries() {
return nullSafe(CLIENT::getRequiredPropertyEntries);
return nullSafe(client::getRequiredPropertyEntries);
}

@Override
public boolean closeAll() {
return nullSafe(CLIENT::closeAll);
return nullSafe(client::closeAll);
}

@Override
public boolean closeScope(String id) {
return nullSafe(() -> CLIENT.closeScope(id));
return nullSafe(() -> client.closeScope(id));
}

@Override
public List<String> getResolvableProperties() {
return nullSafe(CLIENT::getResolvableProperties);
return nullSafe(client::getResolvableProperties);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,19 @@ private Map<String, String> extractAnnotationProperties(TestResourcesProperties
Map<String, String> resolvedProperties = Stream.of(requestedProperties)
.map(v -> new Object() {
private final String key = v;
private final String value = client.resolve(v, Map.of(), testResourcesConfig).orElse(null);
private final String value = resolveProperty();

private String resolveProperty() {
var props = client.getRequiredProperties(v)
.stream()
.map(e -> new Object() {
private final String key = e;
private final Object value = properties.get(e);
})
.filter(o -> o.value != null)
.collect(Collectors.toMap(e -> e.key, e -> e.value));
return client.resolve(v, props, testResourcesConfig).orElse(null);
}
})
.filter(o -> o.value != null)
.collect(Collectors.toMap(e -> e.key, e -> e.value));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2003-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.test.extensions.testresources;

import io.micronaut.context.annotation.Value;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import io.micronaut.test.extensions.testresources.annotation.TestResourcesProperties;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;

@MicronautTest
@TestResourcesProperties(
value = "property-with-requirements",
providers = TestResourcesPropertyProvidersWithRequirementsTest.MyProvider.class
)
public class TestResourcesPropertyProvidersWithRequirementsTest {

@Value("${some-other-property}")
String derivedFromTestResources;

@Test
@DisplayName("properties can be computed from test resources when they have requirements")
public void canDerivePropertiesFromTestResources() {
assertEquals("supplied by test resources with requirements: 42 and transformed", derivedFromTestResources);
}

public static class MyProvider implements TestResourcesPropertyProvider {
@Override
public Map<String, String> provide(Map<String, Object> testProperties) {
String str = (String) testProperties.get("property-with-requirements");
return Map.of(
"some-other-property", str + " and transformed"
);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ test-resources:
log:
regex: ".*Server is ready.*"
toto: 40
required-property: 42
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public class FakeTestResourcesClient implements TestResourcesClient {
private static final Map<String, String> MOCK_PROPERTIES = Map.of(
"first-property", "first supplied by test resources",
"second-property", "second supplied by test resources",
"some-property", "supplied by test resources"
"some-property", "supplied by test resources",
"property-with-requirements", "supplied by test resources with requirements"
);

@Override
Expand All @@ -36,11 +37,22 @@ public List<String> getResolvableProperties(Map<String, Collection<String>> prop

@Override
public Optional<String> resolve(String name, Map<String, Object> properties, Map<String, Object> testResourcesConfig) {
return Optional.ofNullable(MOCK_PROPERTIES.get(name));
var value = MOCK_PROPERTIES.get(name);
if ("property-with-requirements".equals(name)) {
if (!properties.containsKey("required-property")) {
return Optional.empty();
} else {
value += ": " + properties.get("required-property");
}
}
return Optional.ofNullable(value);
}

@Override
public List<String> getRequiredProperties(String expression) {
if ("property-with-requirements".equals(expression)) {
return List.of("required-property");
}
return List.of();
}

Expand Down

0 comments on commit 785d9b7

Please sign in to comment.