Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in the AOT test process if there are two tests that check an actuator endpoint. #34337

Closed
ruben-garciapariente opened this issue Feb 22, 2023 · 13 comments
Labels
for: external-project For an external project and not something we can fix theme: aot An issue related to Ahead-of-time processing type: bug A general bug

Comments

@ruben-garciapariente
Copy link

Hello

I'am using SB 3.0.2. I'm trying to pass the tests with native compilation with mvn -PnativeTest clean install and I get the following error

2023-02-22T09:14:51.320+01:00  WARN 28134 --- [           main] o.s.t.c.aot.TestContextAotGenerator      : Failed to generate AOT artifacts for test classes [com.example.testactuatornative.Test2ITTest]

java.lang.IllegalStateException: java.nio.file.FileAlreadyExistsException: /home/n129586/wks/test/test-actuator-native/target/spring-aot/test/sources/org/springframework/boot/actuate/autoconfigure/endpoint/web/CorsEndpointProperties__ManagementBeanDefinitions.java
        at org.springframework.aot.generate.FileSystemGeneratedFiles.addFile(FileSystemGeneratedFiles.java:97) ~[spring-core-6.0.4.jar:6.0.4]
        at org.springframework.aot.generate.GeneratedFiles.addFile(GeneratedFiles.java:149) ~[spring-core-6.0.4.jar:6.0.4]
        at org.springframework.aot.generate.GeneratedFiles.addSourceFile(GeneratedFiles.java:70) ~[spring-core-6.0.4.jar:6.0.4]
        at org.springframework.aot.generate.GeneratedFiles.addSourceFile(GeneratedFiles.java:47) ~[spring-core-6.0.4.jar:6.0.4]
        at org.springframework.aot.generate.GeneratedClasses.writeTo(GeneratedClasses.java:198) ~[spring-core-6.0.4.jar:6.0.4]
        at org.springframework.aot.generate.DefaultGenerationContext.writeGeneratedContent(DefaultGenerationContext.java:127) ~[spring-core-6.0.4.jar:6.0.4]
        at org.springframework.test.context.aot.TestContextAotGenerator.lambda$processAheadOfTime$4(TestContextAotGenerator.java:209) ~[spring-test-6.0.4.jar:6.0.4]
        at java.base/java.util.Map.forEach(Map.java:713) ~[na:na]
        at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:197) ~[spring-test-6.0.4.jar:6.0.4]
        at org.springframework.test.context.aot.TestContextAotGenerator.processAheadOfTime(TestContextAotGenerator.java:159) ~[spring-test-6.0.4.jar:6.0.4]
        at org.springframework.test.context.aot.TestAotProcessor.performAotProcessing(TestAotProcessor.java:91) ~[spring-test-6.0.4.jar:6.0.4]
        at org.springframework.test.context.aot.TestAotProcessor.doProcess(TestAotProcessor.java:72) ~[spring-test-6.0.4.jar:6.0.4]
        at org.springframework.test.context.aot.TestAotProcessor.doProcess(TestAotProcessor.java:39) ~[spring-test-6.0.4.jar:6.0.4]
        at org.springframework.context.aot.AbstractAotProcessor.process(AbstractAotProcessor.java:82) ~[spring-context-6.0.4.jar:6.0.4]
        at org.springframework.boot.test.context.SpringBootTestAotProcessor.main(SpringBootTestAotProcessor.java:57) ~[spring-boot-test-3.0.2.jar:3.0.2]
Caused by: java.nio.file.FileAlreadyExistsException: /home/n129586/wks/test/test-actuator-native/target/spring-aot/test/sources/org/springframework/boot/actuate/autoconfigure/endpoint/web/CorsEndpointProperties__ManagementBeanDefinitions.java
        at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:94) ~[na:na]
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:106) ~[na:na]
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111) ~[na:na]
        at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:218) ~[na:na]
        at java.base/java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:484) ~[na:na]
        at java.base/java.nio.file.Files.newOutputStream(Files.java:228) ~[na:na]
        at java.base/java.nio.file.Files.copy(Files.java:3160) ~[na:na]
        at org.springframework.aot.generate.FileSystemGeneratedFiles.addFile(FileSystemGeneratedFiles.java:93) ~[spring-core-6.0.4.jar:6.0.4]
        ... 14 common frames omitted

I think this happens if I have two tests of type @SpringBootTest with property management.server.port=0.

I have tried to create a minimal example: https://github.com/ruben-garciapariente/test-actuator-native

Thanks & regards

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 22, 2023
@mhalbritter
Copy link
Contributor

Thanks for the report, there's something wrong here. It seems that if two management contexts exists, it leads to this error.

If i for example remove the value1=value1 and value2=value2 properties from your tests, the context will be cached and the error is gone.

@mhalbritter mhalbritter added type: bug A general bug theme: aot An issue related to Ahead-of-time processing and removed status: waiting-for-triage An issue we've not yet triaged labels Feb 23, 2023
@mhalbritter mhalbritter added this to the 3.0.x milestone Feb 23, 2023
@Jul13nT
Copy link

Jul13nT commented Jun 5, 2023

I stumbled across the same error. Here is my repo with the error: https://github.com/Jul13nT/native-test-actuator

Run ./gradlew test and I get the exact same error.

One difference is that the management.server.port is set globally in application.properties. Then I have one test with @SpringBootTest and one with @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT).

Because of this, none of our tests of all our services are running and it prevents us of using GraalVM. Is there a possible workaround?

@robert-fennell-bk
Copy link

I stumbled across the same error. Here is my repo with the error: https://github.com/Jul13nT/native-test-actuator

Run ./gradlew test and I get the exact same error.

One difference is that the management.server.port is set globally in application.properties. Then I have one test with @SpringBootTest and one with @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT).

Because of this, none of our tests of all our services are running and it prevents us of using GraalVM. Is there a possible workaround?

I also ran into this bug in the same way.

To work around it, I moved all management.* properties into a properties file named application-actuator.properties, and then I'm compiling and running the application with the actuator profile enabled, but during testing I don't activate this profile.

If you do want to create integration tests to verify the actuator, it's still possible by creating a test classes annotated with @ActiveProfiles("actuator"), but you have to be careful not to create multiple test classes with this profile that might also try to change the test context in a different way.

@snicoll
Copy link
Member

snicoll commented Jun 16, 2023

I believe this is a duplicate of spring-projects/spring-framework#28974.

@sbrannen
Copy link
Member

@snicoll
Copy link
Member

snicoll commented Jul 11, 2023

Oh well, a duplicate of spring-projects/spring-framework#30861 then.

@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Jul 11, 2023
@snicoll snicoll added the for: external-project For an external project and not something we can fix label Jul 11, 2023
@snicoll snicoll removed this from the 3.0.x milestone Jul 11, 2023
@sbrannen
Copy link
Member

sbrannen commented Jul 15, 2023

The error can also be reproduced by running the tests in AOT mode on the JVM as follows.

./mvnw clean test spring-boot:process-test-aot && ./mvnw -Dspring.aot.enabled=true test

More importantly...

This issue has been fixed for the upcoming Spring Framework 6.0.12 release (see spring-projects/spring-framework#30861).

To verify things work as expected, I updated pom.xml in the linked project as follows.

	<properties>
		<java.version>17</java.version>
		<spring-framework.version>6.0.12-SNAPSHOT</spring-framework.version>
	</properties>

	<repositories>
		<repository>
			<id>repository.spring.snapshot</id>
			<name>Spring Snapshot Repository</name>
			<url>https://repo.spring.io/snapshot</url>
		</repository>
	</repositories>

With that, the tests now pass in AOT mode on the JVM and within a native image.

@ruben-garciapariente, @Jul13nT, and @robert-fennell-bk: feel free to give it a try with 6.0.12-SNAPSHOT, and let us know if you run into any issues.

@meletis
Copy link

meletis commented Dec 8, 2023

I also ran into this bug in the same way.

To work around it, I moved all management.* properties into a properties file named application-actuator.properties, and then I'm compiling and running the application with the actuator profile enabled, but during testing I don't activate this profile.

If you do want to create integration tests to verify the actuator, it's still possible by creating a test classes annotated with @ActiveProfiles("actuator"), but you have to be careful not to create multiple test classes with this profile that might also try to change the test context in a different way.

@robert-fennell-bk , I also ran into the same issue and I followed your suggestion, but with no luck. I even deleted all my managenent.* and server.* properties as another test but that failed too. In my last test, which also failed, I also removed the org.springframework.boot:spring-boot-starter-actuator dependency completely.

Is there any chance that you can remember what kind of detective work you did back then in order to identify the root cause for your case? I believe I can follow the same steps as you did in order to find out what more/else is special about my app that is still suffering from this bug.

Thank you in advance!

@wilkinsona
Copy link
Member

@meletis what version of Spring Boot are you using? If you have the problem discussed in this issue, it should be fixed in Spring Boot 3.0.11 and later and 3.1.4 and later through the upgrade to Spring Framework 6.0.12. If you're already using such a version of Spring Boot then you may have a different problem.

@meletis
Copy link

meletis commented Dec 8, 2023

@wilkinsona , thanks, but I'm using Spring Boot 3.2.0. Yes, everything was fine until recently, when I was on 3.1.5.

@wilkinsona
Copy link
Member

@meletis, that sounds like it may be a different problem. If you would like us to investigate, please open a new issue and provide a minimal sample that reproduces it.

@meletis
Copy link

meletis commented Dec 8, 2023

@wilkinsona , actually, I just realized that is very similar to #36997, which is also on 3.2.0.

I also just discovered a IntelliJ plugin that can automatically attach the debugger to Java processes spawned by Gradle processes, so I'm now able to debug the TestContextAotGenerator, so I should have a solution soon. I will keep you posted here.

@meletis
Copy link

meletis commented Dec 8, 2023

Okay, that was easy with the debugger.

I managed to reproduce the issue at my repo, using the develop branch: meletis/native-build-tools-bug-report#1

There is one test class that is using an @Autowired instance of the service class and another test class that is using an @MockBean instance of the service class. The difference is what is causing the generation of two MergedContextConfiguration classes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix theme: aot An issue related to Ahead-of-time processing type: bug A general bug
Projects
None yet
Development

No branches or pull requests

9 participants