Prefer modified resources over the originals in TestCompiler

Previously, when the test compiler had been seeded with a resource
file, any modifications to this resource performed during
compilation would be lost as this original content would always
be returned.

This commit updates the DynamicJavaFileManager to always store
the dynamic resource in the dynamicResourceFiles map, irrespective
of whether it's being created afresh or from some existing resource
content. This ensures that any modifications made to the resource
can be retrieved later on.

Similarly, DynamicClassLoader has been updated to prefer dynamic
resource files over any original resource files. This ensures that
the resource that it finds reflects any modifications that have
been made to it.

See gh-33850
This commit is contained in:
Andy Wilkinson
2024-11-06 11:21:05 +00:00
committed by Stéphane Nicoll
parent 9b3cb15389
commit f6e1a5de09
4 changed files with 67 additions and 15 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-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.
@@ -17,6 +17,7 @@
package org.springframework.core.test.tools;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.EnumSet;
@@ -154,6 +155,23 @@ class DynamicJavaFileManagerTests {
"META-INF/second.properties");
}
@Test
void existingResourceFileCanBeUpdated() throws IOException {
try (InputStream input = getResourceOne().openInputStream()) {
assertThat(input).hasContent("a");
}
try (OutputStream output = getResourceOne().openOutputStream()) {
output.write('b');
}
try (InputStream input = getResourceOne().openInputStream()) {
assertThat(input).hasContent("b");
}
}
private FileObject getResourceOne() {
return this.fileManager.getFileForOutput(this.location, "", "com/example/one/resource.one", null);
}
private void writeDummyBytecode(JavaFileObject fileObject) throws IOException {
try (OutputStream outputStream = fileObject.openOutputStream()) {
StreamUtils.copy(DUMMY_BYTECODE, outputStream);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-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.
@@ -16,7 +16,10 @@
package org.springframework.core.test.tools;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -27,6 +30,8 @@ import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.TypeElement;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import com.example.PublicInterface;
import org.junit.jupiter.api.Test;
@@ -367,6 +372,14 @@ class TestCompilerTests {
});
}
@Test
void getUpdatedResourceAsStream() {
SourceFile sourceFile = SourceFile.of(HELLO_WORLD);
TestCompiler.forSystem().withResources(ResourceFile.of("com/example/resource", new byte[] { 'a' }))
.withProcessors(new ResourceModifyingProcessor()).compile(sourceFile, compiled -> assertThat(
compiled.getClassLoader().getResourceAsStream("com/example/resource")).hasContent("b"));
}
private void assertSuppliesHelloWorld(Compiled compiled) {
assertThat(compiled.getInstance(Supplier.class).get()).isEqualTo("Hello World!");
}
@@ -392,4 +405,26 @@ class TestCompilerTests {
}
}
@SupportedAnnotationTypes("java.lang.Deprecated")
static class ResourceModifyingProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (roundEnv.processingOver()) {
try {
FileObject resource = this.processingEnv.getFiler()
.createResource(StandardLocation.CLASS_OUTPUT, "", "com/example/resource");
try (OutputStream output = resource.openOutputStream()) {
output.write('b');
}
}
catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
return true;
}
}
}