From 6b9cd873ca5748525149e91c5a0913318e69fb9b Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 18 Mar 2025 14:27:33 +0100 Subject: [PATCH 1/2] Use gvenzl/oracle-free:23.6-slim which has ARM64 support See gh-35249 --- ...ckerComposeConnectionDetailsFactoryIntegrationTests.java | 6 +----- ...ckerComposeConnectionDetailsFactoryIntegrationTests.java | 6 +----- ...bcContainerConnectionDetailsFactoryIntegrationTests.java | 6 +----- .../boot/testsupport/container/TestImage.java | 2 +- 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleFreeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleFreeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java index 1ce4142013..764985ae3b 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleFreeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleFreeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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. @@ -20,13 +20,11 @@ import java.sql.Driver; import java.time.Duration; import org.awaitility.Awaitility; -import org.junit.jupiter.api.condition.OS; import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails; import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest; import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.testsupport.container.TestImage; -import org.springframework.boot.testsupport.junit.DisabledOnOs; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.SimpleDriverDataSource; import org.springframework.util.ClassUtils; @@ -38,8 +36,6 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Andy Wilkinson */ -@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64", - disabledReason = "The Oracle image has no ARM support") class OracleFreeJdbcDockerComposeConnectionDetailsFactoryIntegrationTests { @SuppressWarnings("unchecked") diff --git a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleFreeR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleFreeR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests.java index 3f9e80cf65..415bf6cb45 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleFreeR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/oracle/OracleFreeR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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. @@ -21,13 +21,11 @@ import java.time.Duration; import io.r2dbc.spi.ConnectionFactories; import io.r2dbc.spi.ConnectionFactoryOptions; import org.awaitility.Awaitility; -import org.junit.jupiter.api.condition.OS; import org.springframework.boot.autoconfigure.r2dbc.R2dbcConnectionDetails; import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest; import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.testsupport.container.TestImage; -import org.springframework.boot.testsupport.junit.DisabledOnOs; import org.springframework.r2dbc.core.DatabaseClient; import static org.assertj.core.api.Assertions.assertThat; @@ -37,8 +35,6 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Andy Wilkinson */ -@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64", - disabledReason = "The Oracle image has no ARM support") class OracleFreeR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests { @DockerComposeTest(composeFile = "oracle-compose.yaml", image = TestImage.ORACLE_FREE) diff --git a/spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/r2dbc/OracleFreeR2dbcContainerConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/r2dbc/OracleFreeR2dbcContainerConnectionDetailsFactoryIntegrationTests.java index 2294e08779..c58193b2dc 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/r2dbc/OracleFreeR2dbcContainerConnectionDetailsFactoryIntegrationTests.java +++ b/spring-boot-project/spring-boot-testcontainers/src/dockerTest/java/org/springframework/boot/testcontainers/service/connection/r2dbc/OracleFreeR2dbcContainerConnectionDetailsFactoryIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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. @@ -20,7 +20,6 @@ import java.time.Duration; import io.r2dbc.spi.ConnectionFactory; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.OS; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.oracle.OracleContainer; @@ -31,7 +30,6 @@ import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration; import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.boot.testsupport.container.TestImage; -import org.springframework.boot.testsupport.junit.DisabledOnOs; import org.springframework.context.annotation.Configuration; import org.springframework.r2dbc.core.DatabaseClient; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; @@ -45,8 +43,6 @@ import static org.assertj.core.api.Assertions.assertThat; */ @SpringJUnitConfig @Testcontainers(disabledWithoutDocker = true) -@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64", - disabledReason = "The Oracle image has no ARM support") class OracleFreeR2dbcContainerConnectionDetailsFactoryIntegrationTests { @Container diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support-docker/src/main/java/org/springframework/boot/testsupport/container/TestImage.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support-docker/src/main/java/org/springframework/boot/testsupport/container/TestImage.java index a87f222860..32eb06ff3c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-test-support-docker/src/main/java/org/springframework/boot/testsupport/container/TestImage.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support-docker/src/main/java/org/springframework/boot/testsupport/container/TestImage.java @@ -132,7 +132,7 @@ public enum TestImage { /** * A container image suitable for testing Oracle Free. */ - ORACLE_FREE("gvenzl/oracle-free", "23.3-slim", () -> org.testcontainers.oracle.OracleContainer.class, + ORACLE_FREE("gvenzl/oracle-free", "23.6-slim", () -> org.testcontainers.oracle.OracleContainer.class, (container) -> ((org.testcontainers.oracle.OracleContainer) container) .withStartupTimeout(Duration.ofMinutes(2))), From 80b6c596696ab84b8539ae54ae5d409f43dcd844 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Tue, 18 Mar 2025 15:31:19 +0100 Subject: [PATCH 2/2] Improve debuggability of DockerComposeTestExtension --- .../test/DockerComposeTestExtension.java | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/test/DockerComposeTestExtension.java b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/test/DockerComposeTestExtension.java index c0ee2a7cf0..d2470524b0 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/test/DockerComposeTestExtension.java +++ b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/test/DockerComposeTestExtension.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 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. @@ -17,6 +17,7 @@ package org.springframework.boot.docker.compose.service.connection.test; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.LinkedHashMap; @@ -39,6 +40,7 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; +import org.springframework.util.FileSystemUtils; import static org.assertj.core.api.Assertions.fail; @@ -46,22 +48,24 @@ import static org.assertj.core.api.Assertions.fail; * {@link Extension} for {@link DockerComposeTest @DockerComposeTest}. * * @author Andy Wilkinson + * @author Moritz Halbritter */ class DockerComposeTestExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback, ParameterResolver { private static final Namespace NAMESPACE = Namespace.create(DockerComposeTestExtension.class); - private static final String STORE_KEY_COMPOSE_FILE = "compose-file"; + private static final String STORE_KEY_WORKSPACE = "workspace"; private static final String STORE_KEY_APPLICATION_CONTEXT = "application-context"; @Override public void beforeTestExecution(ExtensionContext context) throws Exception { - Path transformedComposeFile = prepareComposeFile(context); Store store = context.getStore(NAMESPACE); - store.put(STORE_KEY_COMPOSE_FILE, transformedComposeFile); + Path workspace = Files.createTempDirectory("DockerComposeTestExtension-"); + store.put(STORE_KEY_WORKSPACE, workspace); try { - SpringApplication application = prepareApplication(transformedComposeFile); + Path composeFile = prepareComposeFile(workspace, context); + SpringApplication application = prepareApplication(composeFile); store.put(STORE_KEY_APPLICATION_CONTEXT, application.run()); } catch (Exception ex) { @@ -70,33 +74,33 @@ class DockerComposeTestExtension implements BeforeTestExecutionCallback, AfterTe } } - private Path prepareComposeFile(ExtensionContext context) { + private Path prepareComposeFile(Path workspace, ExtensionContext context) { DockerComposeTest dockerComposeTest = context.getRequiredTestMethod().getAnnotation(DockerComposeTest.class); TestImage image = dockerComposeTest.image(); Resource composeResource = new ClassPathResource(dockerComposeTest.composeFile(), context.getRequiredTestClass()); - return transformedComposeFile(composeResource, image); + return transformedComposeFile(workspace, composeResource, image); } - private Path transformedComposeFile(Resource composeFileResource, TestImage image) { + private Path transformedComposeFile(Path workspace, Resource composeFileResource, TestImage image) { try { - Path composeFile = composeFileResource.getFile().toPath(); - Path transformedComposeFile = Files.createTempFile("", "-" + composeFile.getFileName().toString()); - String transformedContent = Files.readString(composeFile).replace("{imageName}", image.toString()); - Files.writeString(transformedComposeFile, transformedContent); - return transformedComposeFile; + String template = composeFileResource.getContentAsString(StandardCharsets.UTF_8); + String content = template.replace("{imageName}", image.toString()); + Path composeFile = workspace.resolve("compose.yaml"); + Files.writeString(composeFile, content); + return composeFile; } catch (IOException ex) { - fail("Error transforming Docker compose file '" + composeFileResource + "': " + ex.getMessage()); + fail("Error transforming Docker compose file '" + composeFileResource + "': " + ex.getMessage(), ex); + return null; } - return null; } - private SpringApplication prepareApplication(Path transformedComposeFile) { + private SpringApplication prepareApplication(Path composeFile) { SpringApplication application = new SpringApplication(Config.class); Map properties = new LinkedHashMap<>(); properties.put("spring.docker.compose.skip.in-tests", "false"); - properties.put("spring.docker.compose.file", transformedComposeFile); + properties.put("spring.docker.compose.file", composeFile); properties.put("spring.docker.compose.stop.command", "down"); application.setDefaultProperties(properties); return application; @@ -110,7 +114,7 @@ class DockerComposeTestExtension implements BeforeTestExecutionCallback, AfterTe private void cleanUp(ExtensionContext context) throws Exception { Store store = context.getStore(NAMESPACE); runShutdownHandlers(); - deleteComposeFile(store); + deleteWorkspace(store); } private void runShutdownHandlers() { @@ -118,10 +122,10 @@ class DockerComposeTestExtension implements BeforeTestExecutionCallback, AfterTe ((Runnable) shutdownHandlers).run(); } - private void deleteComposeFile(Store store) throws IOException { - Path composeFile = store.get(STORE_KEY_COMPOSE_FILE, Path.class); - if (composeFile != null) { - Files.delete(composeFile); + private void deleteWorkspace(Store store) throws IOException { + Path workspace = (Path) store.get(STORE_KEY_WORKSPACE); + if (workspace != null) { + FileSystemUtils.deleteRecursively(workspace); } }