Skip to content

Commit

Permalink
#284 fix compatibility with Flyway 10.17.1 and above
Browse files Browse the repository at this point in the history
  • Loading branch information
tomix26 committed Nov 25, 2024
1 parent f984a28 commit 2a94033
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 12 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ project(':embedded-database-spring-test') {
"testRuntimeClasspath_${suite.name}_${version.name}" {
extendsFrom testRuntimeClasspath

if (version.flyway != null && version.flyway.startsWith('10.')) {
if (version.flyway != null && (version.flyway.startsWith('10.') || version.flyway.startsWith('11.'))) {
dependencies.add(project.dependencies.create("org.flywaydb:flyway-database-postgresql:${version.flyway}"))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.zonky.test.db.flyway;

import com.google.common.collect.ImmutableList;
import org.aopalliance.intercept.Interceptor;
import org.aopalliance.intercept.MethodInterceptor;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.resolver.MigrationResolver;
Expand Down Expand Up @@ -113,8 +114,7 @@ public Collection<ResolvedMigration> getMigrations() {
if (flywayVersion.isGreaterThanOrEqualTo("9")) {
return invokeMethod(resolver, "resolveMigrations", config);
} else if (flywayVersion.isGreaterThanOrEqualTo("5.2")) {
Class<?> contextType = ClassUtils.forName("org.flywaydb.core.api.resolver.Context", classLoader);
Object contextInstance = ProxyFactory.getProxy(contextType, (MethodInterceptor) invocation ->
Object contextInstance = createMock("org.flywaydb.core.api.resolver.Context", (MethodInterceptor) invocation ->
"getConfiguration".equals(invocation.getMethod().getName()) ? config : invocation.proceed());
return invokeMethod(resolver, "resolveMigrations", contextInstance);
} else {
Expand All @@ -126,7 +126,17 @@ public Collection<ResolvedMigration> getMigrations() {
}

private MigrationResolver createMigrationResolver(Flyway flyway) throws ClassNotFoundException {
if (flywayVersion.isGreaterThanOrEqualTo("8")) {
if (flywayVersion.isGreaterThanOrEqualTo("10.17.1")) {
Object executor = getField(flyway, "flywayExecutor");
Object providers = invokeMethod(executor, "createResourceAndClassProviders", true);
Object resourceProvider = getField(providers, "left");
Object classProvider = getField(providers, "right");
Object sqlScript = createMock("org.flywaydb.core.internal.sqlscript.SqlScript", (MethodInterceptor) invocation -> false);
Object sqlScriptFactory = createMock("org.flywaydb.core.internal.sqlscript.SqlScriptFactory", (MethodInterceptor) invocation -> sqlScript);
Object sqlScriptExecutorFactory = createMock("org.flywaydb.core.internal.sqlscript.SqlScriptExecutorFactory");
Object parsingContext = invokeConstructor("org.flywaydb.core.internal.parser.ParsingContext");
return invokeMethod(executor, "createMigrationResolver", resourceProvider, classProvider, sqlScriptExecutorFactory, sqlScriptFactory, parsingContext, null);
} else if (flywayVersion.isGreaterThanOrEqualTo("8")) {
Object executor = getField(flyway, "flywayExecutor");
Object providers = invokeMethod(executor, "createResourceAndClassProviders", true);
Object resourceProvider = getField(providers, "left");
Expand Down Expand Up @@ -493,4 +503,9 @@ private static Object createMock(String className) throws ClassNotFoundException
Class<?> proxyInterface = ClassUtils.forName(className, classLoader);
return ProxyFactory.getProxy(proxyInterface, (MethodInterceptor) invocation -> null);
}

private static Object createMock(String className, Interceptor interceptor) throws ClassNotFoundException {
Class<?> proxyInterface = ClassUtils.forName(className, classLoader);
return ProxyFactory.getProxy(proxyInterface, interceptor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.opentable.db.postgres.embedded.EmbeddedPostgres;
import io.zonky.test.category.PostgresTestSuite;
import io.zonky.test.db.AutoConfigureEmbeddedDatabase;
import io.zonky.test.support.TestSocketUtils;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
Expand All @@ -28,7 +29,6 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.SocketUtils;

import javax.sql.DataSource;
import java.sql.SQLException;
Expand All @@ -49,7 +49,7 @@ static class Config {

@Bean
public Integer randomPort() {
return SocketUtils.findAvailableTcpPort();
return TestSocketUtils.findAvailableTcpPort();
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.zonky.test.category.PostgresTestSuite;
import io.zonky.test.db.AutoConfigureEmbeddedDatabase;
import io.zonky.test.db.postgres.embedded.EmbeddedPostgres;
import io.zonky.test.support.TestSocketUtils;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
Expand All @@ -28,7 +29,6 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.SocketUtils;

import javax.sql.DataSource;
import java.sql.SQLException;
Expand All @@ -49,7 +49,7 @@ static class Config {

@Bean
public Integer randomPort() {
return SocketUtils.findAvailableTcpPort();
return TestSocketUtils.findAvailableTcpPort();
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.zonky.test.db.preparer.DatabasePreparer;
import io.zonky.test.db.provider.support.BlockingDatabaseWrapper;
import io.zonky.test.db.support.TestDatabasePreparer;
import io.zonky.test.support.TestSocketUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -29,7 +30,6 @@
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.util.SocketUtils;

import javax.sql.DataSource;
import java.sql.SQLException;
Expand Down Expand Up @@ -93,7 +93,7 @@ public void testGetDatabase() throws Exception {

@Test
public void testDatabaseCustomizers() throws Exception {
int randomPort = SocketUtils.findAvailableTcpPort();
int randomPort = TestSocketUtils.findAvailableTcpPort();
when(databaseCustomizers.getIfAvailable()).thenReturn(Collections.singletonList(builder -> builder.setPort(randomPort)));

DatabasePreparer preparer = TestDatabasePreparer.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.zonky.test.db.preparer.DatabasePreparer;
import io.zonky.test.db.provider.support.BlockingDatabaseWrapper;
import io.zonky.test.db.support.TestDatabasePreparer;
import io.zonky.test.support.TestSocketUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -29,7 +30,6 @@
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.util.SocketUtils;

import javax.sql.DataSource;
import java.sql.SQLException;
Expand Down Expand Up @@ -93,7 +93,7 @@ public void testGetDatabase() throws Exception {

@Test
public void testDatabaseCustomizers() throws Exception {
int randomPort = SocketUtils.findAvailableTcpPort();
int randomPort = TestSocketUtils.findAvailableTcpPort();
when(databaseCustomizers.getIfAvailable()).thenReturn(Collections.singletonList(builder -> builder.setPort(randomPort)));

DatabasePreparer preparer = TestDatabasePreparer.empty();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2024 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
*
* http://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.zonky.test.support;

import org.springframework.util.Assert;

import javax.net.ServerSocketFactory;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.util.Random;

public class TestSocketUtils {

private static final int PORT_RANGE_MIN = 1024;
private static final int PORT_RANGE_MAX = 65535;
private static final int PORT_RANGE_PLUS_ONE = PORT_RANGE_MAX - PORT_RANGE_MIN + 1;
private static final int MAX_ATTEMPTS = 1_000;

private static final Random random = new Random(System.nanoTime());

private TestSocketUtils() {}

public static int findAvailableTcpPort() {
int candidatePort;
int searchCounter = 0;
do {
Assert.state(++searchCounter <= MAX_ATTEMPTS, () -> String.format(
"Could not find an available TCP port in the range [%d, %d] after %d attempts",
PORT_RANGE_MIN, PORT_RANGE_MAX, MAX_ATTEMPTS));
candidatePort = PORT_RANGE_MIN + random.nextInt(PORT_RANGE_PLUS_ONE);
}
while (!isPortAvailable(candidatePort));

return candidatePort;
}

private static boolean isPortAvailable(int port) {
try {
ServerSocket serverSocket = ServerSocketFactory.getDefault()
.createServerSocket(port, 1, InetAddress.getByName("localhost"));
serverSocket.close();
return true;
}
catch (Exception ex) {
return false;
}
}
}

0 comments on commit 2a94033

Please sign in to comment.