From ad2d9c0ab1477f5e3677a1a1d551460ba4a60a09 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 29 Jul 2021 17:29:20 +0100 Subject: [PATCH] Customize Cassandra's configuration to reduce container startup time Closes gh-27524 --- ...ndraAutoConfigurationIntegrationTests.java | 8 +--- ...asswordAuthenticationIntegrationTests.java | 12 ++---- ...DataAutoConfigurationIntegrationTests.java | 8 +--- .../DataCassandraTestIntegrationTests.java | 9 ++--- ...TestWithIncludeFilterIntegrationTests.java | 9 ++--- .../spring-boot-test-support/build.gradle | 1 + .../testcontainers/CassandraContainer.java | 39 +++++++++++++++++++ 7 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/CassandraContainer.java diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationIntegrationTests.java index 1a99bcbf563..fb8908b8f14 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationIntegrationTests.java @@ -16,12 +16,9 @@ package org.springframework.boot.autoconfigure.cassandra; -import java.time.Duration; - import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.config.DriverConfigLoader; import org.junit.jupiter.api.Test; -import org.testcontainers.containers.CassandraContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; @@ -30,7 +27,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.boot.testsupport.testcontainers.DockerImageNames; +import org.springframework.boot.testsupport.testcontainers.CassandraContainer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -47,8 +44,7 @@ import static org.mockito.Mockito.verify; class CassandraAutoConfigurationIntegrationTests { @Container - static final CassandraContainer cassandra = new CassandraContainer<>(DockerImageNames.cassandra()) - .withStartupAttempts(5).withStartupTimeout(Duration.ofMinutes(10)); + static final CassandraContainer cassandra = new CassandraContainer(); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of(CassandraAutoConfiguration.class)).withPropertyValues( diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationWithPasswordAuthenticationIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationWithPasswordAuthenticationIntegrationTests.java index a23eec0e128..f9e7c594490 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationWithPasswordAuthenticationIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationWithPasswordAuthenticationIntegrationTests.java @@ -28,7 +28,6 @@ import com.datastax.oss.driver.api.core.cql.SimpleStatement; import org.junit.jupiter.api.Test; import org.rnorth.ducttape.TimeoutException; import org.rnorth.ducttape.unreliables.Unreliables; -import org.testcontainers.containers.CassandraContainer; import org.testcontainers.containers.ContainerLaunchException; import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; import org.testcontainers.images.builder.Transferable; @@ -37,7 +36,7 @@ import org.testcontainers.junit.jupiter.Testcontainers; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.boot.testsupport.testcontainers.DockerImageNames; +import org.springframework.boot.testsupport.testcontainers.CassandraContainer; import org.springframework.util.StreamUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -52,7 +51,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; class CassandraAutoConfigurationWithPasswordAuthenticationIntegrationTests { @Container - static final CassandraContainer cassandra = new PasswordAuthenticatorCassandraContainer().withStartupAttempts(5) + static final CassandraContainer cassandra = new PasswordAuthenticatorCassandraContainer().withStartupAttempts(5) .withStartupTimeout(Duration.ofMinutes(10)).waitingFor(new CassandraWaitStrategy()); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() @@ -81,12 +80,7 @@ class CassandraAutoConfigurationWithPasswordAuthenticationIntegrationTests { .hasMessageContaining("Authentication error")); } - static final class PasswordAuthenticatorCassandraContainer - extends CassandraContainer { - - PasswordAuthenticatorCassandraContainer() { - super(DockerImageNames.cassandra()); - } + static final class PasswordAuthenticatorCassandraContainer extends CassandraContainer { @Override protected void containerIsCreated(String containerId) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationIntegrationTests.java index 1b8677e1bc6..9b203d7161b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationIntegrationTests.java @@ -16,12 +16,9 @@ package org.springframework.boot.autoconfigure.data.cassandra; -import java.time.Duration; - import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.CqlSessionBuilder; import org.junit.jupiter.api.Test; -import org.testcontainers.containers.CassandraContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; @@ -31,7 +28,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.autoconfigure.data.cassandra.city.City; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.boot.testsupport.testcontainers.DockerImageNames; +import org.springframework.boot.testsupport.testcontainers.CassandraContainer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.cassandra.config.SchemaAction; @@ -49,8 +46,7 @@ import static org.assertj.core.api.Assertions.assertThat; class CassandraDataAutoConfigurationIntegrationTests { @Container - static final CassandraContainer cassandra = new CassandraContainer<>(DockerImageNames.cassandra()) - .withStartupAttempts(5).withStartupTimeout(Duration.ofMinutes(10)); + static final CassandraContainer cassandra = new CassandraContainer(); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration( diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestIntegrationTests.java index 26512e3b02e..f6680c90582 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-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. @@ -16,13 +16,11 @@ package org.springframework.boot.test.autoconfigure.data.cassandra; -import java.time.Duration; import java.util.UUID; import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.CqlSessionBuilder; import org.junit.jupiter.api.Test; -import org.testcontainers.containers.CassandraContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; @@ -30,7 +28,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.redis.ExampleService; import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.testsupport.testcontainers.DockerImageNames; +import org.springframework.boot.testsupport.testcontainers.CassandraContainer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.data.cassandra.core.CassandraTemplate; @@ -53,8 +51,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; class DataCassandraTestIntegrationTests { @Container - static final CassandraContainer cassandra = new CassandraContainer<>(DockerImageNames.cassandra()) - .withStartupAttempts(5).withStartupTimeout(Duration.ofMinutes(10)); + static final CassandraContainer cassandra = new CassandraContainer(); @DynamicPropertySource static void cassandraProperties(DynamicPropertyRegistry registry) { diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestWithIncludeFilterIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestWithIncludeFilterIntegrationTests.java index afd43a4de3c..65bc07ea4e9 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestWithIncludeFilterIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestWithIncludeFilterIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-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. @@ -16,19 +16,17 @@ package org.springframework.boot.test.autoconfigure.data.cassandra; -import java.time.Duration; import java.util.UUID; import com.datastax.oss.driver.api.core.CqlSession; import com.datastax.oss.driver.api.core.CqlSessionBuilder; import org.junit.jupiter.api.Test; -import org.testcontainers.containers.CassandraContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.testsupport.testcontainers.DockerImageNames; +import org.springframework.boot.testsupport.testcontainers.CassandraContainer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.stereotype.Service; @@ -53,8 +51,7 @@ import static org.assertj.core.api.Assertions.assertThat; class DataCassandraTestWithIncludeFilterIntegrationTests { @Container - static final CassandraContainer cassandra = new CassandraContainer<>(DockerImageNames.cassandra()) - .withStartupAttempts(5).withStartupTimeout(Duration.ofMinutes(10)); + static final CassandraContainer cassandra = new CassandraContainer(); @DynamicPropertySource static void cassandraProperties(DynamicPropertyRegistry registry) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support/build.gradle b/spring-boot-project/spring-boot-tools/spring-boot-test-support/build.gradle index afcb084d112..05c762da7ec 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-test-support/build.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/build.gradle @@ -18,6 +18,7 @@ dependencies { compileOnly("org.mockito:mockito-core") compileOnly("org.springframework:spring-context") compileOnly("org.springframework.data:spring-data-redis") + compileOnly("org.testcontainers:cassandra") compileOnly("org.testcontainers:testcontainers") implementation("org.apache.maven.resolver:maven-resolver-connector-basic") diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/CassandraContainer.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/CassandraContainer.java new file mode 100644 index 00000000000..c08ff07321c --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/CassandraContainer.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-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 org.springframework.boot.testsupport.testcontainers; + +import java.time.Duration; + +/** + * Custom {@link org.testcontainers.containers.CassandraContainer} tuned to improve + * startup time. + * + * @author Andy Wilkinson + * @since 2.4.10 + */ +public class CassandraContainer extends org.testcontainers.containers.CassandraContainer { + + public CassandraContainer() { + super(DockerImageNames.cassandra()); + withEnv("CASSANDRA_SNITCH", "GossipingPropertyFileSnitch"); + withEnv("JVM_OPTS", "-Dcassandra.skip_wait_for_gossip_to_settle=0 -Dcassandra.initial_token=0"); + withEnv("HEAP_NEWSIZE", "128M"); + withEnv("MAX_HEAP_SIZE", "1024M"); + withStartupTimeout(Duration.ofMinutes(10)); + } + +}