From 2fc512644e37aa609cbd2a3b02bffc0c64391b56 Mon Sep 17 00:00:00 2001 From: fennec Date: Mon, 11 Mar 2024 16:58:38 +0900 Subject: [PATCH 1/2] Change implementation (it.ozimov:embedded-redis > org.signal:embedded-redis) Add Class SocketUtils.kt --- build.gradle.kts | 2 +- gradle.properties | 2 +- .../redis/EmbeddedRedisApplicationListener.kt | 1 - .../asarkar/spring/test/redis/SocketUtils.kt | 153 ++++++++++++++++++ 4 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/com/asarkar/spring/test/redis/SocketUtils.kt diff --git a/build.gradle.kts b/build.gradle.kts index fe61edc..a1edc4e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,7 +40,7 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion") { exclude(group = "com.vaadin.external.google") } - implementation("it.ozimov:embedded-redis:$embeddedRedisVersion") { + implementation("org.signal:embedded-redis:$embeddedRedisVersion") { exclude(group = "org.slf4j", module = "slf4j-simple") } testImplementation("org.springframework.boot:spring-boot-starter:$springBootVersion") diff --git a/gradle.properties b/gradle.properties index 251f764..988e7f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ org.gradle.warning.mode=all org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G springBootVersion=2.5.2 -embeddedRedisVersion=0.7.3 +embeddedRedisVersion=0.8.3 lettuceVersion=6.1.4.RELEASE jUnitVersion=5.7.0 kotlin.version=1.5.20 diff --git a/src/main/kotlin/com/asarkar/spring/test/redis/EmbeddedRedisApplicationListener.kt b/src/main/kotlin/com/asarkar/spring/test/redis/EmbeddedRedisApplicationListener.kt index 9eb4ae5..25e8b03 100644 --- a/src/main/kotlin/com/asarkar/spring/test/redis/EmbeddedRedisApplicationListener.kt +++ b/src/main/kotlin/com/asarkar/spring/test/redis/EmbeddedRedisApplicationListener.kt @@ -5,7 +5,6 @@ import org.springframework.context.ApplicationListener import org.springframework.core.Ordered import org.springframework.core.annotation.Order import org.springframework.core.env.MapPropertySource -import org.springframework.util.SocketUtils @Order(Ordered.LOWEST_PRECEDENCE) open class EmbeddedRedisApplicationListener : ApplicationListener { diff --git a/src/main/kotlin/com/asarkar/spring/test/redis/SocketUtils.kt b/src/main/kotlin/com/asarkar/spring/test/redis/SocketUtils.kt new file mode 100644 index 0000000..37163f7 --- /dev/null +++ b/src/main/kotlin/com/asarkar/spring/test/redis/SocketUtils.kt @@ -0,0 +1,153 @@ +/* + * Copyright 2002-2020 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 com.asarkar.spring.test.redis + +import org.springframework.util.Assert +import java.net.DatagramSocket +import java.net.InetAddress +import java.net.ServerSocket +import java.util.Random +import javax.net.ServerSocketFactory + +/** + * Simple utility methods for working with network sockets for example, + * for finding available ports on `localhost`. + * + * Within this class, a TCP port refers to a port for a [ServerSocket]; + * whereas, a UDP port refers to a port for a [DatagramSocket]. + * + * org.springframework.util.SocketUtils was removed in Spring 6. + * From Springboot 3.2.3 version, SocketUtils cannot be used. + * org.springframework.test.util.TestSocketUtils can be used as an alternative, but embedded-redis-spring has to support older versions, so org.springframework.util.SocketUtils was copied. + * + * @author Sam Brannen + * @author Ben Hale + * @author Arjen Poutsma + * @author Gunnar Hillert + * @author Gary Russell + * @author fennec-fox + * @since 4.0 + */ +object SocketUtils { + /** + * The default minimum value for port ranges used when finding an available + * socket port. + */ + private const val PORT_RANGE_MIN: Int = 1024 + + /** + * The default maximum value for port ranges used when finding an available + * socket port. + */ + const val PORT_RANGE_MAX: Int = 65535 + + private val random = Random(System.nanoTime()) + + /** + * Find an available TCP port randomly selected from the range + * [`minPort`, `maxPort`]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return an available TCP port number + * @throws IllegalStateException if no available port could be found + */ + /** + * Find an available TCP port randomly selected from the range + * [`minPort`, {@value #PORT_RANGE_MAX}]. + * @param minPort the minimum port number + * @return an available TCP port number + * @throws IllegalStateException if no available port could be found + */ + /** + * Find an available TCP port randomly selected from the range + * [{@value #PORT_RANGE_MIN}, {@value #PORT_RANGE_MAX}]. + * @return an available TCP port number + * @throws IllegalStateException if no available port could be found + */ + @JvmOverloads + fun findAvailableTcpPort(minPort: Int = PORT_RANGE_MIN, maxPort: Int = PORT_RANGE_MAX): Int { + return SocketType.TCP.findAvailablePort(minPort, maxPort) + } + + private enum class SocketType { + TCP { + override fun isPortAvailable(port: Int): Boolean { + try { + val serverSocket = ServerSocketFactory.getDefault().createServerSocket( + port, + 1, + InetAddress.getByName("localhost") + ) + serverSocket.close() + return true + } catch (ex: Exception) { + return false + } + } + }; + + /** + * Determine if the specified port for this `SocketType` is + * currently available on `localhost`. + */ + protected abstract fun isPortAvailable(port: Int): Boolean + + /** + * Find a pseudo-random port number within the range + * [`minPort`, `maxPort`]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return a random port number within the specified range + */ + private fun findRandomPort(minPort: Int, maxPort: Int): Int { + val portRange = maxPort - minPort + return minPort + random.nextInt(portRange + 1) + } + + /** + * Find an available port for this `SocketType`, randomly selected + * from the range [`minPort`, `maxPort`]. + * @param minPort the minimum port number + * @param maxPort the maximum port number + * @return an available port number for this socket type + * @throws IllegalStateException if no available port could be found + */ + fun findAvailablePort(minPort: Int, maxPort: Int): Int { + Assert.isTrue(minPort > 0, "'minPort' must be greater than 0") + Assert.isTrue(maxPort >= minPort, "'maxPort' must be greater than or equal to 'minPort'") + Assert.isTrue(maxPort <= PORT_RANGE_MAX, "'maxPort' must be less than or equal to $PORT_RANGE_MAX") + + val portRange = maxPort - minPort + var candidatePort: Int + var searchCounter = 0 + do { + check(searchCounter <= portRange) { + String.format( + "Could not find an available %s port in the range [%d, %d] after %d attempts", + name, + minPort, + maxPort, + searchCounter + ) + } + candidatePort = findRandomPort(minPort, maxPort) + searchCounter++ + } while (!isPortAvailable(candidatePort)) + + return candidatePort + } + } +} From f007835d4f6b801b211fddf961958f71e5c34d9f Mon Sep 17 00:00:00 2001 From: fennec Date: Thu, 14 Mar 2024 14:00:01 +0900 Subject: [PATCH 2/2] corrections to the modification request. --- README.md | 2 +- .../asarkar/spring/test/redis/SocketUtils.kt | 30 ++----------------- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 1cab680..5fddfe6 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Starts a Redis server and makes the port available as Spring Boot environment property. Stops the server when the Spring context is destroyed. -Requires Java 8 or later. Uses [embedded-redis](https://github.com/ozimov/embedded-redis) and [Spring Boot](https://spring.io/projects/spring-boot). +Requires Java 8 or later. Uses [embedded-redis](https://github.com/signalapp/embedded-redis) and [Spring Boot](https://spring.io/projects/spring-boot). ## Installation diff --git a/src/main/kotlin/com/asarkar/spring/test/redis/SocketUtils.kt b/src/main/kotlin/com/asarkar/spring/test/redis/SocketUtils.kt index 37163f7..33d9150 100644 --- a/src/main/kotlin/com/asarkar/spring/test/redis/SocketUtils.kt +++ b/src/main/kotlin/com/asarkar/spring/test/redis/SocketUtils.kt @@ -1,18 +1,3 @@ -/* - * Copyright 2002-2020 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 com.asarkar.spring.test.redis import org.springframework.util.Assert @@ -33,13 +18,8 @@ import javax.net.ServerSocketFactory * From Springboot 3.2.3 version, SocketUtils cannot be used. * org.springframework.test.util.TestSocketUtils can be used as an alternative, but embedded-redis-spring has to support older versions, so org.springframework.util.SocketUtils was copied. * - * @author Sam Brannen - * @author Ben Hale - * @author Arjen Poutsma - * @author Gunnar Hillert - * @author Gary Russell * @author fennec-fox - * @since 4.0 + * @since 1.1.2 */ object SocketUtils { /** @@ -135,13 +115,7 @@ object SocketUtils { var searchCounter = 0 do { check(searchCounter <= portRange) { - String.format( - "Could not find an available %s port in the range [%d, %d] after %d attempts", - name, - minPort, - maxPort, - searchCounter - ) + "Could not find an available $name port in the range [$minPort, $maxPort] after $searchCounter attempts" } candidatePort = findRandomPort(minPort, maxPort) searchCounter++