diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/sql_load_script/AbsoluteFileSystemPathSqlLoadScriptTestCase.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/sql_load_script/SqlLoadScriptAbsoluteFileSystemPathTestCase.java similarity index 61% rename from extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/sql_load_script/AbsoluteFileSystemPathSqlLoadScriptTestCase.java rename to extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/sql_load_script/SqlLoadScriptAbsoluteFileSystemPathTestCase.java index 92098b9031bf6..3c21d68f1fecc 100644 --- a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/sql_load_script/AbsoluteFileSystemPathSqlLoadScriptTestCase.java +++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/sql_load_script/SqlLoadScriptAbsoluteFileSystemPathTestCase.java @@ -4,6 +4,7 @@ import java.net.URISyntaxException; import java.net.URL; +import java.nio.file.Path; import java.nio.file.Paths; import org.junit.jupiter.api.Assertions; @@ -25,18 +26,28 @@ * * See https://github.com/quarkusio/quarkus/issues/23574 */ -public class AbsoluteFileSystemPathSqlLoadScriptTestCase { +public class SqlLoadScriptAbsoluteFileSystemPathTestCase { private static final String sqlLoadScriptAbsolutePath; + private static final String escapedSqlLoadScriptAbsolutePath; static { // For this reproducer, we need the absolute path to a file // that actually exists in src/test/resources - URL resource = AbsoluteFileSystemPathSqlLoadScriptTestCase.class.getResource("/import.sql"); + URL resource = SqlLoadScriptAbsoluteFileSystemPathTestCase.class.getResource("/import.sql"); + Path path; try { - sqlLoadScriptAbsolutePath = Paths.get(resource.toURI()).toAbsolutePath().toString(); + path = Paths.get(resource.toURI()).toAbsolutePath(); } catch (URISyntaxException e) { throw new IllegalStateException(e); } - System.out.println("Absolute filesystem path used for sql-load-script: " + sqlLoadScriptAbsolutePath); + sqlLoadScriptAbsolutePath = path.toString(); + System.out.println("Absolute filesystem path used in test: " + sqlLoadScriptAbsolutePath); + if (path.getFileSystem().getSeparator().equals("\\")) { + // "\" is a meta-character in property files, and thus it needs to be escaped for Windows paths. + escapedSqlLoadScriptAbsolutePath = sqlLoadScriptAbsolutePath.replace("\\", "\\\\"); + } else { + escapedSqlLoadScriptAbsolutePath = sqlLoadScriptAbsolutePath; + } + System.out.println("Escaped absolute filesystem path passed to sql-load-script: " + escapedSqlLoadScriptAbsolutePath); } @RegisterExtension @@ -44,11 +55,12 @@ public class AbsoluteFileSystemPathSqlLoadScriptTestCase { .withApplicationRoot((jar) -> jar .addClasses(MyEntity.class)) .withConfigurationResource("application.properties") - .overrideConfigKey("quarkus.hibernate-orm.sql-load-script", sqlLoadScriptAbsolutePath) + .overrideConfigKey("quarkus.hibernate-orm.sql-load-script", escapedSqlLoadScriptAbsolutePath) .assertException(t -> assertThat(t) .isInstanceOf(ConfigurationException.class) - .hasMessageContainingAll("Unable to interpret path referenced in 'quarkus.hibernate-orm.sql-load-script=", - "import.sql'", + .hasMessageContainingAll( + "Unable to interpret path referenced in 'quarkus.hibernate-orm.sql-load-script=" + + sqlLoadScriptAbsolutePath + "'", "Expected a path relative to the root of the path tree")); @Test diff --git a/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/sql_load_script/SqlLoadScriptAbsoluteFileSystemPathUnescapedOnWindowsTestCase.java b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/sql_load_script/SqlLoadScriptAbsoluteFileSystemPathUnescapedOnWindowsTestCase.java new file mode 100644 index 0000000000000..21a05ffc20e54 --- /dev/null +++ b/extensions/hibernate-orm/deployment/src/test/java/io/quarkus/hibernate/orm/sql_load_script/SqlLoadScriptAbsoluteFileSystemPathUnescapedOnWindowsTestCase.java @@ -0,0 +1,73 @@ +package io.quarkus.hibernate.orm.sql_load_script; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.hibernate.orm.MyEntity; +import io.quarkus.runtime.configuration.ConfigurationException; +import io.quarkus.test.QuarkusUnitTest; + +/** + * Test that setting {@code quarkus.hibernate-orm.sql-load-script} + * to the absolute path to a resource file on the filesystem on Windows, + * while also forgetting about the fact that backslashes need to be escaped in properties files, + * makes the build fail. + * + * Added while working on https://github.com/quarkusio/quarkus/issues/23574, + * because we noticed such paths cannot be correctly detected as being absolute + * (they cannot be distinguished from a weird relative path to a file starting with "C:" and not containing any backslash). + */ +@EnabledOnOs(OS.WINDOWS) +public class SqlLoadScriptAbsoluteFileSystemPathUnescapedOnWindowsTestCase { + private static final String sqlLoadScriptAbsolutePath; + static { + // For this reproducer, we need the absolute path to a file + // that actually exists in src/test/resources + URL resource = SqlLoadScriptAbsoluteFileSystemPathUnescapedOnWindowsTestCase.class.getResource("/import.sql"); + Path path; + try { + path = Paths.get(resource.toURI()).toAbsolutePath(); + } catch (URISyntaxException e) { + throw new IllegalStateException(e); + } + System.out.println("Absolute filesystem path used in test: " + path); + // This path will contain "\", + // which is a meta-character and will be stripped by Quarkus when parsing the properties file, + // resulting in the path being interpreted wrongly. + // That's exactly what we want: we want to check that a user forgetting to escape backslashes + // in a Windows path in a properties file will still get an error messsage, + // even though it's not that clear. + sqlLoadScriptAbsolutePath = path.toString(); + System.out.println("(Unescaped) absolute filesystem path passed to sql-load-script: " + sqlLoadScriptAbsolutePath); + } + + @RegisterExtension + static QuarkusUnitTest runner = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(MyEntity.class)) + .withConfigurationResource("application.properties") + .overrideConfigKey("quarkus.hibernate-orm.sql-load-script", sqlLoadScriptAbsolutePath) + .assertException(t -> assertThat(t) + .isInstanceOf(ConfigurationException.class) + .hasMessageContainingAll("Unable to find file referenced in 'quarkus.hibernate-orm.sql-load-script=" + // The path will appear without the backslashes in the error message; + // hopefully that'll be enough to hint at what went wrong. + + sqlLoadScriptAbsolutePath.replaceAll("\\.", "") + "'", + "Remove property or add file to your path")); + + @Test + public void testSqlLoadScriptAbsolutePath() { + // deployment exception should happen first + Assertions.fail(); + } +}