You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a Gradle project uses "testImplementation project(path: ':projectname', configuration: 'configurationname')" a Quarkus-vs-JVM class loader conflict appears very late in test execution
#27213
Closed
jskillin-idt opened this issue
Aug 9, 2022
· 5 comments
This was a particularly strange, very nasty-to-debug issue so this one may require some discussion.
First, some background: in a Maven version of a Quarkus project, there was a project structure listed here as "the easy way" to reuse some test code between projects. This influenced the project's transition to Gradle, in which the test sources of one library were wired up to be exported as a JAR under a separate configuration so that another project could depend on them and reuse them.
Gradle itself was perfectly happy with the very simplistic approach and wired up the classpath to test and run correctly.
Quarkus, however, did not appreciate these shenanigans. Very late into the test run, there were quite a lot of class loader errors, and strangely if the dependencies were tweaked, that would seemingly "fix" one error and another would appear.
Expected behavior
Quarkus is able to read the rather niche dependency list and still run.
Actual behavior
Quarkus gives a variety of stack traces fairly late in the test run, such as:
java.lang.LinkageError: loader constraint violation for class org.acme.test.EndToEnd_IT: when selecting overriding method 'org.apache.camel.builder.RouteBuilder org.acme.test.EndToEnd_IT.createRouteBuilder(java.util.Collection, java.util.Collection)' the class loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @4fb392c4 of the selected method's type org.acme.test.EndToEnd_IT, and the class loader 'app' for its super type org.acme.test.AbstractEndToEnd have different Class objects for the type org.apache.camel.builder.RouteBuilder used in the signature (org.acme.test.EndToEnd_IT is in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @4fb392c4, parent loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @3956b302; org.acme.test.AbstractEndToEnd is in unnamed module of loader 'app')
Or, in the reproducer:
java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
org/acme/ExampleTest.afterAll()V @7: invokestatic
Reason:
Type 'org/acme/util/SaySomethingTesty' (current frame, stack[0]) is not assignable to 'org/acme/util/SaySomething'
Current Frame:
bci: @7
flags: { }
locals: { }
stack: { 'org/acme/util/SaySomethingTesty' }
Bytecode:
0000000: bb00 0b59 b700 0cb8 000d b1
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:398)
at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:987)
at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:977)
[snip]
Run ./gradlew :app:test (the "extra-lib" tests will fail for inconsequential reasons)
For comparison while debugging, I've provided a version of the project which succeeds, under the branch "test-fixtures".
Output of uname -a or ver
Linux jacob-ubuntu-dev 5.15.0-43-generic #46-Ubuntu SMP Tue Jul 12 10:30:17 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Output of java -version
openjdk version "11.0.16" 2022-07-19 OpenJDK Runtime Environment (build 11.0.16+8-post-Ubuntu-0ubuntu122.04) OpenJDK 64-Bit Server VM (build 11.0.16+8-post-Ubuntu-0ubuntu122.04, mixed mode, sharing)
GraalVM version (if different from Java)
No response
Quarkus version or git rev
2.11.2.Final
Build tool (ie. output of mvnw --version or gradlew --version)
Gradle 7.4.1
Additional information
Gradle is a build tool that has overwhelming flexibility in what it can do, so it's not surprising to me that going off the officially-documented path discovers corner cases in plugins like Quarkus which try to wrap that complexity with their own logic and build instructions.
The particular use case that allowed me to discover this bug is invalid because an official feature called test fixtures codifies exactly what was desired, and Quarkus happens to work just fine if this feature is used instead.
However, in my humble opinion, this bug is still valid as it reveals a corner case in how dependencies are handled, and that corner case might come up again in a more obscure use case.
The text was updated successfully, but these errors were encountered:
The reproducer was updated to be far slimmer, since it was built on an old reproducer and in fact was reproducing that bug as well 😆 The latest commits should be good to go.
jskillin-idt
changed the title
When a Gradle project uses "testImplementation project(path: ':projectname', configuration: 'configurationname')" Quarkus ignores the dependency, creating a class loader conflict very late in test execution
When a Gradle project uses "testImplementation project(path: ':projectname', configuration: 'configurationname')" a Quarkus-vs-JVM class loader conflict appears very late in test execution
Aug 9, 2022
Describe the bug
This was a particularly strange, very nasty-to-debug issue so this one may require some discussion.
First, some background: in a Maven version of a Quarkus project, there was a project structure listed here as "the easy way" to reuse some test code between projects. This influenced the project's transition to Gradle, in which the test sources of one library were wired up to be exported as a JAR under a separate configuration so that another project could depend on them and reuse them.
Gradle itself was perfectly happy with the very simplistic approach and wired up the classpath to test and run correctly.
Quarkus, however, did not appreciate these shenanigans. Very late into the test run, there were quite a lot of class loader errors, and strangely if the dependencies were tweaked, that would seemingly "fix" one error and another would appear.
Expected behavior
Quarkus is able to read the rather niche dependency list and still run.
Actual behavior
Quarkus gives a variety of stack traces fairly late in the test run, such as:
java.lang.LinkageError: loader constraint violation for class org.acme.test.EndToEnd_IT: when selecting overriding method 'org.apache.camel.builder.RouteBuilder org.acme.test.EndToEnd_IT.createRouteBuilder(java.util.Collection, java.util.Collection)' the class loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @4fb392c4 of the selected method's type org.acme.test.EndToEnd_IT, and the class loader 'app' for its super type org.acme.test.AbstractEndToEnd have different Class objects for the type org.apache.camel.builder.RouteBuilder used in the signature (org.acme.test.EndToEnd_IT is in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @4fb392c4, parent loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @3956b302; org.acme.test.AbstractEndToEnd is in unnamed module of loader 'app')
Or, in the reproducer:
How to Reproduce?
Reproducer: https://github.com/jskillin-idt/quarkusio-quarkus-issues-27213
./gradlew :app:test
(the "extra-lib" tests will fail for inconsequential reasons)For comparison while debugging, I've provided a version of the project which succeeds, under the branch "test-fixtures".
Output of
uname -a
orver
Linux jacob-ubuntu-dev 5.15.0-43-generic #46-Ubuntu SMP Tue Jul 12 10:30:17 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Output of
java -version
openjdk version "11.0.16" 2022-07-19 OpenJDK Runtime Environment (build 11.0.16+8-post-Ubuntu-0ubuntu122.04) OpenJDK 64-Bit Server VM (build 11.0.16+8-post-Ubuntu-0ubuntu122.04, mixed mode, sharing)
GraalVM version (if different from Java)
No response
Quarkus version or git rev
2.11.2.Final
Build tool (ie. output of
mvnw --version
orgradlew --version
)Gradle 7.4.1
Additional information
Gradle is a build tool that has overwhelming flexibility in what it can do, so it's not surprising to me that going off the officially-documented path discovers corner cases in plugins like Quarkus which try to wrap that complexity with their own logic and build instructions.
The particular use case that allowed me to discover this bug is invalid because an official feature called test fixtures codifies exactly what was desired, and Quarkus happens to work just fine if this feature is used instead.
However, in my humble opinion, this bug is still valid as it reveals a corner case in how dependencies are handled, and that corner case might come up again in a more obscure use case.
The text was updated successfully, but these errors were encountered: