diff --git a/pom.xml b/pom.xml index 89ddae70b..1aacbf6ea 100644 --- a/pom.xml +++ b/pom.xml @@ -274,6 +274,12 @@ 0.9.1 test + + com.redis + testcontainers-redis + 2.2.2 + test + org.signal libsignal-server diff --git a/service/pom.xml b/service/pom.xml index 0a9a8e6a4..411a47cf9 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -484,6 +484,12 @@ test + + com.redis + testcontainers-redis + test + + com.fasterxml.uuid java-uuid-generator diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/redis/RedisServerExtension.java b/service/src/test/java/org/whispersystems/textsecuregcm/redis/RedisServerExtension.java index d232f1bdc..ae05029b0 100644 --- a/service/src/test/java/org/whispersystems/textsecuregcm/redis/RedisServerExtension.java +++ b/service/src/test/java/org/whispersystems/textsecuregcm/redis/RedisServerExtension.java @@ -5,29 +5,28 @@ package org.whispersystems.textsecuregcm.redis; -import static org.junit.jupiter.api.Assumptions.assumeFalse; - +import com.redis.testcontainers.RedisContainer; import io.lettuce.core.FlushMode; import io.lettuce.core.RedisURI; import io.lettuce.core.resource.ClientResources; -import java.io.IOException; -import java.net.ServerSocket; import java.time.Duration; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; +import org.testcontainers.utility.DockerImageName; import org.whispersystems.textsecuregcm.configuration.CircuitBreakerConfiguration; import org.whispersystems.textsecuregcm.configuration.RetryConfiguration; -import redis.embedded.RedisServer; -import redis.embedded.exceptions.EmbeddedRedisException; public class RedisServerExtension implements BeforeAllCallback, BeforeEachCallback, ExtensionContext.Store.CloseableResource { - private static RedisServer redisServer; + private static RedisContainer redisContainer; private static ClientResources redisClientResources; private FaultTolerantRedisClient faultTolerantRedisClient; + // redis:7.4-apline; see https://hub.docker.com/layers/library/redis/7.4-alpine/images/sha256-e1b05db81cda983ede3bbb3e834e7ebec8faafa275f55f7f91f3ee84114f98a7 + private static final DockerImageName REDIS_IMAGE = DockerImageName.parse("redis@sha256:af1d0fc3f63b02b13ff7906c9baf7c5b390b8881ca08119cd570677fe2f60b55"); + public static class RedisServerExtensionBuilder { private RedisServerExtensionBuilder() { @@ -43,25 +42,17 @@ public class RedisServerExtension implements BeforeAllCallback, BeforeEachCallba } @Override - public void beforeAll(final ExtensionContext context) throws Exception { - assumeFalse(System.getProperty("os.name").equalsIgnoreCase("windows")); - - if (redisServer == null) { - redisServer = RedisServer.builder() - .setting("appendonly no") - .setting("save \"\"") - .setting("dir " + System.getProperty("java.io.tmpdir")) - .port(getAvailablePort()) - .build(); + public void beforeAll(final ExtensionContext context) { + if (redisContainer == null) { + redisContainer = new RedisContainer(REDIS_IMAGE); + redisContainer.start(); redisClientResources = ClientResources.builder().build(); - - startWithRetries(3); } } public static RedisURI getRedisURI() { - return RedisURI.create("redis://127.0.0.1:%d".formatted(redisServer.ports().getFirst())); + return RedisURI.create(redisContainer.getRedisURI()); } @Override @@ -80,34 +71,16 @@ public class RedisServerExtension implements BeforeAllCallback, BeforeEachCallba @Override public void close() throws Throwable { - if (redisServer != null) { + if (redisContainer != null) { redisClientResources.shutdown().await(); - redisServer.stop(); + redisContainer.stop(); } redisClientResources = null; - redisServer = null; + redisContainer = null; } public FaultTolerantRedisClient getRedisClient() { return faultTolerantRedisClient; } - - private static int getAvailablePort() throws IOException { - try (ServerSocket socket = new ServerSocket(0)) { - return socket.getLocalPort(); - } - } - - private void startWithRetries(int attemptsLeft) throws Exception { - try { - redisServer.start(); - } catch (final EmbeddedRedisException e) { - if (attemptsLeft == 0) { - throw e; - } - Thread.sleep(500); - startWithRetries(attemptsLeft - 1); - } - } }