Fix test for incremental build of renamed properties class

Previously, the .class file for the renamed properties class was
on the class path of the compilation in two places:

1. The output directory of the test's previous compilation
2. The output directory of the compilation of src/test/java of
   spring-boot-configuration-processor

The first of these locations is addressed by updating TestProject.
The .class file is now deleted from the project's output location
at the same time as the .java file is deleted from its source
location.

The second of these locations is addressed by configuring the class
path of the compiler to include a copy of the result of compiling
src/test/java of spring-boot-configuration-processor. From this copy
entries can then be deleted as needed without destabilizing other tests.

Closes gh-26271
This commit is contained in:
Andy Wilkinson 2023-10-30 14:11:56 +00:00
parent c999d987a9
commit 94e810201e
3 changed files with 39 additions and 8 deletions

View File

@ -16,7 +16,6 @@
package org.springframework.boot.configurationprocessor;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
@ -74,7 +73,6 @@ class IncrementalBuildMetadataGenerationTests extends AbstractMetadataGeneration
}
@Test
@Disabled("gh-26271")
void incrementalBuildTypeRenamed() throws Exception {
TestProject project = new TestProject(this.tempDir, FooProperties.class, BarProperties.class);
ConfigurationMetadata metadata = project.fullBuild();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2023 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.
@ -23,15 +23,18 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
import org.springframework.boot.configurationprocessor.test.TestConfigurationMetadataAnnotationProcessor;
import org.springframework.boot.configurationsample.ConfigurationProperties;
import org.springframework.boot.configurationsample.NestedConfigurationProperty;
import org.springframework.boot.testsupport.BuildOutput;
import org.springframework.boot.testsupport.compiler.TestCompiler;
import org.springframework.boot.testsupport.compiler.TestCompiler.TestCompilationTask;
import org.springframework.util.Assert;
@ -56,21 +59,41 @@ public class TestProject {
* Contains copies of the original source so we can modify it safely to test
* incremental builds.
*/
private File sourceDirectory;
private final File sourceDirectory;
private TestCompiler compiler;
private final TestCompiler compiler;
private Set<File> sourceFiles = new LinkedHashSet<>();
private final Set<File> sourceFiles = new LinkedHashSet<>();
private final File classPathDirectory;
public TestProject(File tempDirectory, Class<?>... classes) throws IOException {
this.sourceDirectory = new File(tempDirectory, "src");
this.compiler = new TestCompiler(new File(tempDirectory, "build")) {
File outputDirectory = new File(tempDirectory, "build");
File testClasses = new BuildOutput(TestProject.class).getTestClassesLocation();
this.classPathDirectory = new File(tempDirectory, "classPath");
FileSystemUtils.copyRecursively(testClasses, this.classPathDirectory);
this.compiler = new TestCompiler(outputDirectory) {
@Override
protected File getSourceDirectory() {
return TestProject.this.sourceDirectory;
}
@Override
protected Iterable<? extends File> prepareClassPath(Iterable<? extends File> classPath) {
List<File> updatedClassPath = new ArrayList<>();
for (File entry : classPath) {
if (!entry.equals(testClasses)) {
updatedClassPath.add(entry);
}
else {
updatedClassPath.add(TestProject.this.classPathDirectory);
}
}
return updatedClassPath;
}
};
Set<Class<?>> contents = new HashSet<>(Arrays.asList(classes));
contents.addAll(Arrays.asList(ALWAYS_INCLUDE));
@ -143,13 +166,17 @@ public class TestProject {
}
/**
* Delete source file for given class from project.
* Delete from the project the source {@code .java} file and any compiled
* {@code .class} file for the given class.
* @param type the class to delete
*/
public void delete(Class<?> type) {
File target = getSourceFile(type);
target.delete();
this.sourceFiles.remove(target);
String fileName = type.getName().replace(".", "/") + ".class";
new File(this.compiler.getOutputLocation(), fileName).delete();
new File(this.classPathDirectory, fileName).delete();
}
/**

View File

@ -62,6 +62,8 @@ public class TestCompiler {
Iterable<? extends File> temp = Collections.singletonList(this.outputLocation);
this.fileManager.setLocation(StandardLocation.CLASS_OUTPUT, temp);
this.fileManager.setLocation(StandardLocation.SOURCE_OUTPUT, temp);
Iterable<? extends File> classPath = this.fileManager.getLocation(StandardLocation.CLASS_PATH);
this.fileManager.setLocation(StandardLocation.CLASS_PATH, prepareClassPath(classPath));
}
public TestCompilationTask getTask(Collection<File> sourceFiles) {
@ -103,6 +105,10 @@ public class TestCompiler {
return SOURCE_DIRECTORY;
}
protected Iterable<? extends File> prepareClassPath(Iterable<? extends File> classPath) {
return classPath;
}
/**
* A compilation task.
*/