Skip to content

Commit f6e1a5d

Browse files
wilkinsonasnicoll
authored andcommitted
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
1 parent 9b3cb15 commit f6e1a5d

File tree

4 files changed

+67
-15
lines changed

4 files changed

+67
-15
lines changed

Diff for: spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassLoader.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -121,14 +121,14 @@ protected URL findResource(String name) {
121121
return createResourceUrl(name, () -> classBytes);
122122
}
123123
}
124-
ResourceFile resourceFile = this.resourceFiles.get(name);
125-
if (resourceFile != null) {
126-
return createResourceUrl(resourceFile.getPath(), resourceFile::getBytes);
127-
}
128124
DynamicResourceFileObject dynamicResourceFile = this.dynamicResourceFiles.get(name);
129125
if (dynamicResourceFile != null && dynamicResourceFile.getBytes() != null) {
130126
return createResourceUrl(dynamicResourceFile.getName(), dynamicResourceFile::getBytes);
131127
}
128+
ResourceFile resourceFile = this.resourceFiles.get(name);
129+
if (resourceFile != null) {
130+
return createResourceUrl(resourceFile.getPath(), resourceFile::getBytes);
131+
}
132132
return super.findResource(name);
133133
}
134134

Diff for: spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicJavaFileManager.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -70,13 +70,12 @@ public ClassLoader getClassLoader(Location location) {
7070
}
7171

7272
@Override
73-
public FileObject getFileForOutput(Location location, String packageName,
74-
String relativeName, FileObject sibling) {
75-
ResourceFile resourceFile = this.resourceFiles.get(relativeName);
76-
if (resourceFile != null) {
77-
return new DynamicResourceFileObject(relativeName, resourceFile.getContent());
78-
}
79-
return this.dynamicResourceFiles.computeIfAbsent(relativeName, DynamicResourceFileObject::new);
73+
public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) {
74+
return this.dynamicResourceFiles.computeIfAbsent(relativeName, name -> {
75+
ResourceFile resourceFile = this.resourceFiles.get(name);
76+
return (resourceFile != null) ? new DynamicResourceFileObject(name, resourceFile.getContent())
77+
: new DynamicResourceFileObject(name);
78+
});
8079
}
8180

8281
@Override

Diff for: spring-core-test/src/test/java/org/springframework/core/test/tools/DynamicJavaFileManagerTests.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
1717
package org.springframework.core.test.tools;
1818

1919
import java.io.IOException;
20+
import java.io.InputStream;
2021
import java.io.OutputStream;
2122
import java.util.EnumSet;
2223

@@ -154,6 +155,23 @@ void getFileForOutputReturnsFile() throws Exception {
154155
"META-INF/second.properties");
155156
}
156157

158+
@Test
159+
void existingResourceFileCanBeUpdated() throws IOException {
160+
try (InputStream input = getResourceOne().openInputStream()) {
161+
assertThat(input).hasContent("a");
162+
}
163+
try (OutputStream output = getResourceOne().openOutputStream()) {
164+
output.write('b');
165+
}
166+
try (InputStream input = getResourceOne().openInputStream()) {
167+
assertThat(input).hasContent("b");
168+
}
169+
}
170+
171+
private FileObject getResourceOne() {
172+
return this.fileManager.getFileForOutput(this.location, "", "com/example/one/resource.one", null);
173+
}
174+
157175
private void writeDummyBytecode(JavaFileObject fileObject) throws IOException {
158176
try (OutputStream outputStream = fileObject.openOutputStream()) {
159177
StreamUtils.copy(DUMMY_BYTECODE, outputStream);

Diff for: spring-core-test/src/test/java/org/springframework/core/test/tools/TestCompilerTests.java

+36-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,7 +16,10 @@
1616

1717
package org.springframework.core.test.tools;
1818

19+
import java.io.IOException;
1920
import java.io.InputStream;
21+
import java.io.OutputStream;
22+
import java.io.UncheckedIOException;
2023
import java.util.ArrayList;
2124
import java.util.List;
2225
import java.util.Set;
@@ -27,6 +30,8 @@
2730
import javax.annotation.processing.RoundEnvironment;
2831
import javax.annotation.processing.SupportedAnnotationTypes;
2932
import javax.lang.model.element.TypeElement;
33+
import javax.tools.FileObject;
34+
import javax.tools.StandardLocation;
3035

3136
import com.example.PublicInterface;
3237
import org.junit.jupiter.api.Test;
@@ -367,6 +372,14 @@ void getResourceForCompiledBytecode() {
367372
});
368373
}
369374

375+
@Test
376+
void getUpdatedResourceAsStream() {
377+
SourceFile sourceFile = SourceFile.of(HELLO_WORLD);
378+
TestCompiler.forSystem().withResources(ResourceFile.of("com/example/resource", new byte[] { 'a' }))
379+
.withProcessors(new ResourceModifyingProcessor()).compile(sourceFile, compiled -> assertThat(
380+
compiled.getClassLoader().getResourceAsStream("com/example/resource")).hasContent("b"));
381+
}
382+
370383
private void assertSuppliesHelloWorld(Compiled compiled) {
371384
assertThat(compiled.getInstance(Supplier.class).get()).isEqualTo("Hello World!");
372385
}
@@ -392,4 +405,26 @@ public List<TypeElement> getProcessedAnnotations() {
392405
}
393406
}
394407

408+
@SupportedAnnotationTypes("java.lang.Deprecated")
409+
static class ResourceModifyingProcessor extends AbstractProcessor {
410+
411+
@Override
412+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
413+
if (roundEnv.processingOver()) {
414+
try {
415+
FileObject resource = this.processingEnv.getFiler()
416+
.createResource(StandardLocation.CLASS_OUTPUT, "", "com/example/resource");
417+
try (OutputStream output = resource.openOutputStream()) {
418+
output.write('b');
419+
}
420+
}
421+
catch (IOException ex) {
422+
throw new UncheckedIOException(ex);
423+
}
424+
}
425+
return true;
426+
}
427+
428+
}
429+
395430
}

0 commit comments

Comments
 (0)