Replace Spring Boot TestCompiler with Spring Framework's version
See gh-31266
This commit is contained in:
parent
8b2fd6a05a
commit
d25a99692f
|
|
@ -12,5 +12,6 @@ dependencies {
|
||||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||||
testImplementation("org.assertj:assertj-core")
|
testImplementation("org.assertj:assertj-core")
|
||||||
testImplementation("org.springframework:spring-core")
|
testImplementation("org.springframework:spring-core")
|
||||||
|
testImplementation("org.springframework:spring-core-test")
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,46 +16,38 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigureprocessor;
|
package org.springframework.boot.autoconfigureprocessor;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
|
||||||
|
|
||||||
import org.springframework.boot.testsupport.compiler.TestCompiler;
|
import org.springframework.core.test.tools.SourceFile;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.core.test.tools.TestCompiler;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link AutoConfigureAnnotationProcessor}.
|
* Tests for {@link AutoConfigureAnnotationProcessor}.
|
||||||
*
|
*
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
* @author Moritz Halbritter
|
* @author Moritz Halbritter
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
class AutoConfigureAnnotationProcessorTests {
|
class AutoConfigureAnnotationProcessorTests {
|
||||||
|
|
||||||
@TempDir
|
|
||||||
File tempDir;
|
|
||||||
|
|
||||||
private TestCompiler compiler;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void createCompiler() throws IOException {
|
|
||||||
this.compiler = new TestCompiler(this.tempDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void annotatedClass() throws Exception {
|
void annotatedClass() throws Exception {
|
||||||
Properties properties = compile(TestClassConfiguration.class);
|
compile(TestClassConfiguration.class, (properties) -> {
|
||||||
assertThat(properties).hasSize(7);
|
assertThat(properties).hasSize(7);
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestClassConfiguration.ConditionalOnClass",
|
"org.springframework.boot.autoconfigureprocessor.TestClassConfiguration.ConditionalOnClass",
|
||||||
"java.io.InputStream,org.springframework.boot.autoconfigureprocessor."
|
"java.io.InputStream,org.springframework.boot.autoconfigureprocessor."
|
||||||
+ "TestClassConfiguration$Nested,org.springframework.foo");
|
+ "TestClassConfiguration$Nested,org.springframework.foo");
|
||||||
assertThat(properties).containsKey("org.springframework.boot.autoconfigureprocessor.TestClassConfiguration");
|
assertThat(properties)
|
||||||
|
.containsKey("org.springframework.boot.autoconfigureprocessor.TestClassConfiguration");
|
||||||
assertThat(properties)
|
assertThat(properties)
|
||||||
.containsKey("org.springframework.boot.autoconfigureprocessor.TestClassConfiguration$Nested");
|
.containsKey("org.springframework.boot.autoconfigureprocessor.TestClassConfiguration$Nested");
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
|
|
@ -65,11 +57,12 @@ class AutoConfigureAnnotationProcessorTests {
|
||||||
+ "TestClassConfiguration.ConditionalOnSingleCandidate", "java.io.OutputStream");
|
+ "TestClassConfiguration.ConditionalOnSingleCandidate", "java.io.OutputStream");
|
||||||
assertThat(properties).containsEntry("org.springframework.boot.autoconfigureprocessor."
|
assertThat(properties).containsEntry("org.springframework.boot.autoconfigureprocessor."
|
||||||
+ "TestClassConfiguration.ConditionalOnWebApplication", "SERVLET");
|
+ "TestClassConfiguration.ConditionalOnWebApplication", "SERVLET");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void annotatedClassWithOnlyAutoConfiguration() throws Exception {
|
void annotatedClassWithOnlyAutoConfiguration() {
|
||||||
Properties properties = compile(TestAutoConfigurationOnlyConfiguration.class);
|
compile(TestAutoConfigurationOnlyConfiguration.class, (properties) -> {
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationOnlyConfiguration", "");
|
"org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationOnlyConfiguration", "");
|
||||||
assertThat(properties).doesNotContainEntry(
|
assertThat(properties).doesNotContainEntry(
|
||||||
|
|
@ -78,26 +71,27 @@ class AutoConfigureAnnotationProcessorTests {
|
||||||
assertThat(properties).doesNotContainEntry(
|
assertThat(properties).doesNotContainEntry(
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationOnlyConfiguration.AutoConfigureBefore",
|
"org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationOnlyConfiguration.AutoConfigureBefore",
|
||||||
"");
|
"");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void annotatedClassWithOnBeanThatHasName() throws Exception {
|
void annotatedClassWithOnBeanThatHasName() {
|
||||||
Properties properties = compile(TestOnBeanWithNameClassConfiguration.class);
|
compile(TestOnBeanWithNameClassConfiguration.class, (properties) -> {
|
||||||
assertThat(properties).hasSize(2);
|
assertThat(properties).hasSize(2);
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestOnBeanWithNameClassConfiguration.ConditionalOnBean",
|
"org.springframework.boot.autoconfigureprocessor.TestOnBeanWithNameClassConfiguration.ConditionalOnBean",
|
||||||
"");
|
"");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void annotatedMethod() throws Exception {
|
void annotatedMethod() {
|
||||||
Properties properties = compile(TestMethodConfiguration.class);
|
process(TestMethodConfiguration.class, (properties) -> assertThat(properties).isNull());
|
||||||
assertThat(properties).isNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void annotatedClassWithOrder() throws Exception {
|
void annotatedClassWithOrder() {
|
||||||
Properties properties = compile(TestOrderedClassConfiguration.class);
|
compile(TestOrderedClassConfiguration.class, (properties) -> {
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestOrderedClassConfiguration.ConditionalOnClass",
|
"org.springframework.boot.autoconfigureprocessor.TestOrderedClassConfiguration.ConditionalOnClass",
|
||||||
"java.io.InputStream,java.io.OutputStream");
|
"java.io.InputStream,java.io.OutputStream");
|
||||||
|
|
@ -109,11 +103,13 @@ class AutoConfigureAnnotationProcessorTests {
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestOrderedClassConfiguration.AutoConfigureOrder",
|
"org.springframework.boot.autoconfigureprocessor.TestOrderedClassConfiguration.AutoConfigureOrder",
|
||||||
"123");
|
"123");
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void annotatedClassWithAutoConfiguration() throws Exception {
|
void annotatedClassWithAutoConfiguration() throws Exception {
|
||||||
Properties properties = compile(TestAutoConfigurationConfiguration.class);
|
compile(TestAutoConfigurationConfiguration.class, (properties) -> {
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationConfiguration", "");
|
"org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationConfiguration", "");
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
|
|
@ -122,11 +118,12 @@ class AutoConfigureAnnotationProcessorTests {
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationConfiguration.AutoConfigureAfter",
|
"org.springframework.boot.autoconfigureprocessor.TestAutoConfigurationConfiguration.AutoConfigureAfter",
|
||||||
"java.io.OutputStream,test.after1,test.after2");
|
"java.io.OutputStream,test.after1,test.after2");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void annotatedClassWithAutoConfigurationMerged() throws Exception {
|
void annotatedClassWithAutoConfigurationMerged() throws Exception {
|
||||||
Properties properties = compile(TestMergedAutoConfigurationConfiguration.class);
|
compile(TestMergedAutoConfigurationConfiguration.class, (properties) -> {
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestMergedAutoConfigurationConfiguration", "");
|
"org.springframework.boot.autoconfigureprocessor.TestMergedAutoConfigurationConfiguration", "");
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
|
|
@ -135,26 +132,55 @@ class AutoConfigureAnnotationProcessorTests {
|
||||||
assertThat(properties).containsEntry(
|
assertThat(properties).containsEntry(
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestMergedAutoConfigurationConfiguration.AutoConfigureAfter",
|
"org.springframework.boot.autoconfigureprocessor.TestMergedAutoConfigurationConfiguration.AutoConfigureAfter",
|
||||||
"java.io.OutputStream,test.after1,test.after2,java.io.ObjectOutputStream,test.after3,test.after4");
|
"java.io.OutputStream,test.after1,test.after2,java.io.ObjectOutputStream,test.after3,test.after4");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // gh-19370
|
@Test // gh-19370
|
||||||
void propertiesAreFullRepeatable() throws Exception {
|
void propertiesAreFullRepeatable() throws Exception {
|
||||||
String first = new String(
|
process(TestOrderedClassConfiguration.class, (firstFile) -> {
|
||||||
FileCopyUtils.copyToByteArray(process(TestOrderedClassConfiguration.class).getWrittenFile()));
|
String first = getFileContents(firstFile);
|
||||||
String second = new String(
|
process(TestOrderedClassConfiguration.class, (secondFile) -> {
|
||||||
FileCopyUtils.copyToByteArray(process(TestOrderedClassConfiguration.class).getWrittenFile()));
|
String second = getFileContents(secondFile);
|
||||||
assertThat(first).isEqualTo(second).doesNotContain("#");
|
assertThat(first).isEqualTo(second).doesNotContain("#");
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Properties compile(Class<?>... types) throws IOException {
|
private void compile(Class<?> type, Consumer<Properties> consumer) {
|
||||||
return process(types).getWrittenProperties();
|
process(type, (writtenFile) -> consumer.accept(getWrittenProperties(writtenFile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private TestAutoConfigureAnnotationProcessor process(Class<?>... types) {
|
private void process(Class<?> type, Consumer<InputStream> consumer) {
|
||||||
TestAutoConfigureAnnotationProcessor processor = new TestAutoConfigureAnnotationProcessor(
|
TestAutoConfigureAnnotationProcessor processor = new TestAutoConfigureAnnotationProcessor();
|
||||||
this.compiler.getOutputLocation());
|
SourceFile sourceFile = SourceFile.forTestClass(type);
|
||||||
this.compiler.getTask(types).call(processor);
|
TestCompiler compiler = TestCompiler.forSystem().withProcessors(processor).withSources(sourceFile);
|
||||||
return processor;
|
compiler.compile((compiled) -> {
|
||||||
|
InputStream propertiesFile = compiled.getClassLoader()
|
||||||
|
.getResourceAsStream(AutoConfigureAnnotationProcessor.PROPERTIES_PATH);
|
||||||
|
consumer.accept(propertiesFile);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Properties getWrittenProperties(InputStream inputStream) {
|
||||||
|
try {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.load(inputStream);
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
fail("Error reading properties", ex);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFileContents(InputStream inputStream) {
|
||||||
|
try {
|
||||||
|
return new String(inputStream.readAllBytes());
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
fail("Error reading contents of properties file", ex);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigureprocessor;
|
package org.springframework.boot.autoconfigureprocessor;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||||
|
|
||||||
|
|
@ -29,6 +25,7 @@ import javax.annotation.processing.SupportedAnnotationTypes;
|
||||||
* Version of {@link AutoConfigureAnnotationProcessor} used for testing.
|
* Version of {@link AutoConfigureAnnotationProcessor} used for testing.
|
||||||
*
|
*
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
@SupportedAnnotationTypes({ "org.springframework.boot.autoconfigureprocessor.TestConditionalOnClass",
|
@SupportedAnnotationTypes({ "org.springframework.boot.autoconfigureprocessor.TestConditionalOnClass",
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestConditionalOnBean",
|
"org.springframework.boot.autoconfigureprocessor.TestConditionalOnBean",
|
||||||
|
|
@ -40,10 +37,7 @@ import javax.annotation.processing.SupportedAnnotationTypes;
|
||||||
"org.springframework.boot.autoconfigureprocessor.TestAutoConfiguration" })
|
"org.springframework.boot.autoconfigureprocessor.TestAutoConfiguration" })
|
||||||
public class TestAutoConfigureAnnotationProcessor extends AutoConfigureAnnotationProcessor {
|
public class TestAutoConfigureAnnotationProcessor extends AutoConfigureAnnotationProcessor {
|
||||||
|
|
||||||
private final File outputLocation;
|
public TestAutoConfigureAnnotationProcessor() {
|
||||||
|
|
||||||
public TestAutoConfigureAnnotationProcessor(File outputLocation) {
|
|
||||||
this.outputLocation = outputLocation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -69,20 +63,4 @@ public class TestAutoConfigureAnnotationProcessor extends AutoConfigureAnnotatio
|
||||||
return generators;
|
return generators;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Properties getWrittenProperties() throws IOException {
|
|
||||||
File file = getWrittenFile();
|
|
||||||
if (!file.exists()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try (FileInputStream inputStream = new FileInputStream(file)) {
|
|
||||||
Properties properties = new Properties();
|
|
||||||
properties.load(inputStream);
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getWrittenFile() {
|
|
||||||
return new File(this.outputLocation, PROPERTIES_PATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ dependencies {
|
||||||
testCompileOnly("com.google.code.findbugs:jsr305:3.0.2")
|
testCompileOnly("com.google.code.findbugs:jsr305:3.0.2")
|
||||||
testImplementation(enforcedPlatform(project(":spring-boot-project:spring-boot-dependencies")))
|
testImplementation(enforcedPlatform(project(":spring-boot-project:spring-boot-dependencies")))
|
||||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||||
|
testImplementation("org.springframework:spring-core-test")
|
||||||
testImplementation("jakarta.validation:jakarta.validation-api")
|
testImplementation("jakarta.validation:jakarta.validation-api")
|
||||||
testImplementation("org.assertj:assertj-core")
|
testImplementation("org.assertj:assertj-core")
|
||||||
testImplementation("org.hamcrest:hamcrest-library")
|
testImplementation("org.hamcrest:hamcrest-library")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -36,6 +36,7 @@ import org.springframework.boot.configurationprocessor.metadata.JsonMarshaller;
|
||||||
* A {@code MetadataStore} is responsible for the storage of metadata on the filesystem.
|
* A {@code MetadataStore} is responsible for the storage of metadata on the filesystem.
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Scott Frederick
|
||||||
* @since 1.2.2
|
* @since 1.2.2
|
||||||
*/
|
*/
|
||||||
public class MetadataStore {
|
public class MetadataStore {
|
||||||
|
|
@ -76,7 +77,7 @@ public class MetadataStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigurationMetadata readMetadata(InputStream in) throws IOException {
|
private ConfigurationMetadata readMetadata(InputStream in) throws IOException {
|
||||||
try {
|
try (in) {
|
||||||
return new JsonMarshaller().read(in);
|
return new JsonMarshaller().read(in);
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
|
|
@ -87,9 +88,6 @@ public class MetadataStore {
|
||||||
"Invalid additional meta-data in '" + METADATA_PATH + "': " + ex.getMessage(),
|
"Invalid additional meta-data in '" + METADATA_PATH + "': " + ex.getMessage(),
|
||||||
Diagnostic.Kind.ERROR);
|
Diagnostic.Kind.ERROR);
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileObject getMetadataResource() throws IOException {
|
private FileObject getMetadataResource() throws IOException {
|
||||||
|
|
@ -104,9 +102,27 @@ public class MetadataStore {
|
||||||
// Most build systems will have copied the file to the class output location
|
// Most build systems will have copied the file to the class output location
|
||||||
FileObject fileObject = this.environment.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "",
|
FileObject fileObject = this.environment.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "",
|
||||||
ADDITIONAL_METADATA_PATH);
|
ADDITIONAL_METADATA_PATH);
|
||||||
|
InputStream inputStream = getMetadataStream(fileObject);
|
||||||
|
if (inputStream != null) {
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
try {
|
||||||
File file = locateAdditionalMetadataFile(new File(fileObject.toUri()));
|
File file = locateAdditionalMetadataFile(new File(fileObject.toUri()));
|
||||||
return (file.exists() ? new FileInputStream(file) : fileObject.toUri().toURL().openStream());
|
return (file.exists() ? new FileInputStream(file) : fileObject.toUri().toURL().openStream());
|
||||||
}
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new FileNotFoundException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream getMetadataStream(FileObject fileObject) {
|
||||||
|
try {
|
||||||
|
return fileObject.openInputStream();
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
File locateAdditionalMetadataFile(File standardLocation) throws IOException {
|
File locateAdditionalMetadataFile(File standardLocation) throws IOException {
|
||||||
if (standardLocation.exists()) {
|
if (standardLocation.exists()) {
|
||||||
|
|
|
||||||
|
|
@ -16,50 +16,58 @@
|
||||||
|
|
||||||
package org.springframework.boot.configurationprocessor;
|
package org.springframework.boot.configurationprocessor;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
|
||||||
|
|
||||||
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
||||||
|
import org.springframework.boot.configurationprocessor.test.CompiledMetadataReader;
|
||||||
import org.springframework.boot.configurationprocessor.test.TestConfigurationMetadataAnnotationProcessor;
|
import org.springframework.boot.configurationprocessor.test.TestConfigurationMetadataAnnotationProcessor;
|
||||||
import org.springframework.boot.testsupport.compiler.TestCompiler;
|
import org.springframework.core.test.tools.ResourceFile;
|
||||||
|
import org.springframework.core.test.tools.SourceFile;
|
||||||
|
import org.springframework.core.test.tools.TestCompiler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base test infrastructure for metadata generation tests.
|
* Base test infrastructure for metadata generation tests.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractMetadataGenerationTests {
|
public abstract class AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
@TempDir
|
private static final String ADDITIONAL_METADATA_FILE = "META-INF/additional-spring-configuration-metadata.json";
|
||||||
File tempDir;
|
|
||||||
|
|
||||||
private TestCompiler compiler;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void createCompiler() throws IOException {
|
|
||||||
this.compiler = new TestCompiler(this.tempDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TestCompiler getCompiler() {
|
|
||||||
return this.compiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ConfigurationMetadata compile(Class<?>... types) {
|
protected ConfigurationMetadata compile(Class<?>... types) {
|
||||||
TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor(
|
TestCompiler compiler = TestCompiler.forSystem().withSources(sourceFilesOf(types));
|
||||||
this.compiler.getOutputLocation());
|
return compile(compiler);
|
||||||
this.compiler.getTask(types).call(processor);
|
|
||||||
return processor.getMetadata();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ConfigurationMetadata compile(File... sources) {
|
protected ConfigurationMetadata compile(String additionalMetadata, Class<?> type, Class<?>... types) {
|
||||||
TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor(
|
TestCompiler compiler = TestCompiler.forSystem().withSources(sourceFilesOf(type))
|
||||||
this.compiler.getOutputLocation());
|
.withSources(sourceFilesOf(types))
|
||||||
this.compiler.getTask(Arrays.asList(sources)).call(processor);
|
.withResources(ResourceFile.of(ADDITIONAL_METADATA_FILE, additionalMetadata));
|
||||||
return processor.getMetadata();
|
return compile(compiler);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ConfigurationMetadata compile(String... source) {
|
||||||
|
TestCompiler compiler = TestCompiler.forSystem().withSources(sourceFilesOf(source));
|
||||||
|
return compile(compiler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigurationMetadata compile(TestCompiler compiler) {
|
||||||
|
TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor();
|
||||||
|
compiler = compiler.withProcessors(processor);
|
||||||
|
AtomicReference<ConfigurationMetadata> configurationMetadata = new AtomicReference<>();
|
||||||
|
compiler.compile((compiled) -> configurationMetadata.set(CompiledMetadataReader.getMetadata(compiled)));
|
||||||
|
return configurationMetadata.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SourceFile> sourceFilesOf(Class<?>... types) {
|
||||||
|
return Arrays.stream(types).map(SourceFile::forTestClass).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SourceFile> sourceFilesOf(String... content) {
|
||||||
|
return Arrays.stream(content).map(SourceFile::of).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,9 @@
|
||||||
|
|
||||||
package org.springframework.boot.configurationprocessor;
|
package org.springframework.boot.configurationprocessor;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
|
||||||
|
|
||||||
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
||||||
import org.springframework.boot.configurationprocessor.metadata.ItemMetadata;
|
import org.springframework.boot.configurationprocessor.metadata.ItemMetadata;
|
||||||
|
|
@ -60,9 +56,10 @@ import org.springframework.boot.configurationsample.specific.InvalidDefaultValue
|
||||||
import org.springframework.boot.configurationsample.specific.InvalidDoubleRegistrationProperties;
|
import org.springframework.boot.configurationsample.specific.InvalidDoubleRegistrationProperties;
|
||||||
import org.springframework.boot.configurationsample.specific.SimplePojo;
|
import org.springframework.boot.configurationsample.specific.SimplePojo;
|
||||||
import org.springframework.boot.configurationsample.specific.StaticAccessor;
|
import org.springframework.boot.configurationsample.specific.StaticAccessor;
|
||||||
|
import org.springframework.core.test.tools.CompilationException;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link ConfigurationMetadataAnnotationProcessor}.
|
* Tests for {@link ConfigurationMetadataAnnotationProcessor}.
|
||||||
|
|
@ -73,6 +70,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||||
* @author Kris De Volder
|
* @author Kris De Volder
|
||||||
* @author Jonas Keßler
|
* @author Jonas Keßler
|
||||||
* @author Pavel Anisimov
|
* @author Pavel Anisimov
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
class ConfigurationMetadataAnnotationProcessorTests extends AbstractMetadataGenerationTests {
|
class ConfigurationMetadataAnnotationProcessorTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
|
|
@ -374,26 +372,30 @@ class ConfigurationMetadataAnnotationProcessorTests extends AbstractMetadataGene
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void invalidDoubleRegistration() {
|
void invalidDoubleRegistration() {
|
||||||
assertThatIllegalStateException().isThrownBy(() -> compile(InvalidDoubleRegistrationProperties.class))
|
assertThatExceptionOfType(CompilationException.class)
|
||||||
.withMessageContaining("Compilation failed");
|
.isThrownBy(() -> compile(InvalidDoubleRegistrationProperties.class))
|
||||||
|
.withMessageContaining("Unable to compile source");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void constructorParameterPropertyWithInvalidDefaultValueOnNumber() {
|
void constructorParameterPropertyWithInvalidDefaultValueOnNumber() {
|
||||||
assertThatIllegalStateException().isThrownBy(() -> compile(InvalidDefaultValueNumberProperties.class))
|
assertThatExceptionOfType(CompilationException.class)
|
||||||
.withMessageContaining("Compilation failed");
|
.isThrownBy(() -> compile(InvalidDefaultValueNumberProperties.class))
|
||||||
|
.withMessageContaining("Unable to compile source");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void constructorParameterPropertyWithInvalidDefaultValueOnFloatingPoint() {
|
void constructorParameterPropertyWithInvalidDefaultValueOnFloatingPoint() {
|
||||||
assertThatIllegalStateException().isThrownBy(() -> compile(InvalidDefaultValueFloatingPointProperties.class))
|
assertThatExceptionOfType(CompilationException.class)
|
||||||
.withMessageContaining("Compilation failed");
|
.isThrownBy(() -> compile(InvalidDefaultValueFloatingPointProperties.class))
|
||||||
|
.withMessageContaining("Unable to compile source");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void constructorParameterPropertyWithInvalidDefaultValueOnCharacter() {
|
void constructorParameterPropertyWithInvalidDefaultValueOnCharacter() {
|
||||||
assertThatIllegalStateException().isThrownBy(() -> compile(InvalidDefaultValueCharacterProperties.class))
|
assertThatExceptionOfType(CompilationException.class)
|
||||||
.withMessageContaining("Compilation failed");
|
.isThrownBy(() -> compile(InvalidDefaultValueCharacterProperties.class))
|
||||||
|
.withMessageContaining("Unable to compile source");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -411,31 +413,27 @@ class ConfigurationMetadataAnnotationProcessorTests extends AbstractMetadataGene
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void recordProperties(@TempDir File temp) throws IOException {
|
void recordProperties() throws IOException {
|
||||||
File exampleRecord = new File(temp, "ExampleRecord.java");
|
String source = """
|
||||||
try (PrintWriter writer = new PrintWriter(new FileWriter(exampleRecord))) {
|
@org.springframework.boot.configurationsample.ConfigurationProperties("implicit")
|
||||||
writer.println("@org.springframework.boot.configurationsample.ConfigurationProperties(\"implicit\")");
|
public record ExampleRecord(String someString, Integer someInteger) {
|
||||||
writer.println("public record ExampleRecord(String someString, Integer someInteger) {");
|
|
||||||
writer.println("}");
|
|
||||||
}
|
}
|
||||||
ConfigurationMetadata metadata = compile(exampleRecord);
|
""";
|
||||||
|
ConfigurationMetadata metadata = compile(source);
|
||||||
assertThat(metadata).has(Metadata.withProperty("implicit.some-string"));
|
assertThat(metadata).has(Metadata.withProperty("implicit.some-string"));
|
||||||
assertThat(metadata).has(Metadata.withProperty("implicit.some-integer"));
|
assertThat(metadata).has(Metadata.withProperty("implicit.some-integer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void recordPropertiesWithDefaultValues(@TempDir File temp) throws IOException {
|
void recordPropertiesWithDefaultValues() throws IOException {
|
||||||
File exampleRecord = new File(temp, "ExampleRecord.java");
|
String source = """
|
||||||
try (PrintWriter writer = new PrintWriter(new FileWriter(exampleRecord))) {
|
@org.springframework.boot.configurationsample.ConfigurationProperties("record.defaults")
|
||||||
writer.println(
|
public record ExampleRecord(
|
||||||
"@org.springframework.boot.configurationsample.ConfigurationProperties(\"record.defaults\")");
|
@org.springframework.boot.configurationsample.DefaultValue("An1s9n") String someString,
|
||||||
writer.println("public record ExampleRecord(");
|
@org.springframework.boot.configurationsample.DefaultValue("594") Integer someInteger) {
|
||||||
writer.println("@org.springframework.boot.configurationsample.DefaultValue(\"An1s9n\") String someString,");
|
|
||||||
writer.println("@org.springframework.boot.configurationsample.DefaultValue(\"594\") Integer someInteger");
|
|
||||||
writer.println(") {");
|
|
||||||
writer.println("}");
|
|
||||||
}
|
}
|
||||||
ConfigurationMetadata metadata = compile(exampleRecord);
|
""";
|
||||||
|
ConfigurationMetadata metadata = compile(source);
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withProperty("record.defaults.some-string", String.class).withDefaultValue("An1s9n"));
|
.has(Metadata.withProperty("record.defaults.some-string", String.class).withDefaultValue("An1s9n"));
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
|
|
@ -443,21 +441,20 @@ class ConfigurationMetadataAnnotationProcessorTests extends AbstractMetadataGene
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void multiConstructorRecordProperties(@TempDir File temp) throws IOException {
|
void multiConstructorRecordProperties() throws IOException {
|
||||||
File exampleRecord = new File(temp, "ExampleRecord.java");
|
String source = """
|
||||||
try (PrintWriter writer = new PrintWriter(new FileWriter(exampleRecord))) {
|
@org.springframework.boot.configurationsample.ConfigurationProperties("multi")
|
||||||
writer.println("@org.springframework.boot.configurationsample.ConfigurationProperties(\"multi\")");
|
public record ExampleRecord(String someString, Integer someInteger) {
|
||||||
writer.println("public record ExampleRecord(String someString, Integer someInteger) {");
|
@org.springframework.boot.configurationsample.ConstructorBinding
|
||||||
writer.println(" @org.springframework.boot.configurationsample.ConstructorBinding");
|
public ExampleRecord(String someString) {
|
||||||
writer.println(" public ExampleRecord(String someString) {");
|
this(someString, 42);
|
||||||
writer.println(" this(someString, 42);");
|
|
||||||
writer.println(" }");
|
|
||||||
writer.println(" public ExampleRecord(Integer someInteger) {");
|
|
||||||
writer.println(" this(\"someString\", someInteger);");
|
|
||||||
writer.println(" }");
|
|
||||||
writer.println("}");
|
|
||||||
}
|
}
|
||||||
ConfigurationMetadata metadata = compile(exampleRecord);
|
public ExampleRecord(Integer someInteger) {
|
||||||
|
this("someString", someInteger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
ConfigurationMetadata metadata = compile(source);
|
||||||
assertThat(metadata).has(Metadata.withProperty("multi.some-string"));
|
assertThat(metadata).has(Metadata.withProperty("multi.some-string"));
|
||||||
assertThat(metadata).doesNotHave(Metadata.withProperty("multi.some-integer"));
|
assertThat(metadata).doesNotHave(Metadata.withProperty("multi.some-integer"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -36,6 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* Metadata generation tests for Actuator endpoints.
|
* Metadata generation tests for Actuator endpoints.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
class EndpointMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
class EndpointMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
|
|
@ -96,8 +97,8 @@ class EndpointMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void incrementalEndpointBuildChangeGeneralEnabledFlag() throws Exception {
|
void incrementalEndpointBuildChangeGeneralEnabledFlag() throws Exception {
|
||||||
TestProject project = new TestProject(this.tempDir, IncrementalEndpoint.class);
|
TestProject project = new TestProject(IncrementalEndpoint.class);
|
||||||
ConfigurationMetadata metadata = project.fullBuild();
|
ConfigurationMetadata metadata = project.compile();
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withGroup("management.endpoint.incremental").fromSource(IncrementalEndpoint.class));
|
.has(Metadata.withGroup("management.endpoint.incremental").fromSource(IncrementalEndpoint.class));
|
||||||
assertThat(metadata).has(enabledFlag("incremental", true));
|
assertThat(metadata).has(enabledFlag("incremental", true));
|
||||||
|
|
@ -105,7 +106,7 @@ class EndpointMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
assertThat(metadata.getItems()).hasSize(3);
|
assertThat(metadata.getItems()).hasSize(3);
|
||||||
project.replaceText(IncrementalEndpoint.class, "id = \"incremental\"",
|
project.replaceText(IncrementalEndpoint.class, "id = \"incremental\"",
|
||||||
"id = \"incremental\", enableByDefault = false");
|
"id = \"incremental\", enableByDefault = false");
|
||||||
metadata = project.incrementalBuild(IncrementalEndpoint.class);
|
metadata = project.compile();
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withGroup("management.endpoint.incremental").fromSource(IncrementalEndpoint.class));
|
.has(Metadata.withGroup("management.endpoint.incremental").fromSource(IncrementalEndpoint.class));
|
||||||
assertThat(metadata).has(enabledFlag("incremental", false));
|
assertThat(metadata).has(enabledFlag("incremental", false));
|
||||||
|
|
@ -115,15 +116,15 @@ class EndpointMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void incrementalEndpointBuildChangeCacheFlag() throws Exception {
|
void incrementalEndpointBuildChangeCacheFlag() throws Exception {
|
||||||
TestProject project = new TestProject(this.tempDir, IncrementalEndpoint.class);
|
TestProject project = new TestProject(IncrementalEndpoint.class);
|
||||||
ConfigurationMetadata metadata = project.fullBuild();
|
ConfigurationMetadata metadata = project.compile();
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withGroup("management.endpoint.incremental").fromSource(IncrementalEndpoint.class));
|
.has(Metadata.withGroup("management.endpoint.incremental").fromSource(IncrementalEndpoint.class));
|
||||||
assertThat(metadata).has(enabledFlag("incremental", true));
|
assertThat(metadata).has(enabledFlag("incremental", true));
|
||||||
assertThat(metadata).has(cacheTtl("incremental"));
|
assertThat(metadata).has(cacheTtl("incremental"));
|
||||||
assertThat(metadata.getItems()).hasSize(3);
|
assertThat(metadata.getItems()).hasSize(3);
|
||||||
project.replaceText(IncrementalEndpoint.class, "@Nullable String param", "String param");
|
project.replaceText(IncrementalEndpoint.class, "@Nullable String param", "String param");
|
||||||
metadata = project.incrementalBuild(IncrementalEndpoint.class);
|
metadata = project.compile();
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withGroup("management.endpoint.incremental").fromSource(IncrementalEndpoint.class));
|
.has(Metadata.withGroup("management.endpoint.incremental").fromSource(IncrementalEndpoint.class));
|
||||||
assertThat(metadata).has(enabledFlag("incremental", true));
|
assertThat(metadata).has(enabledFlag("incremental", true));
|
||||||
|
|
@ -132,14 +133,14 @@ class EndpointMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void incrementalEndpointBuildEnableSpecificEndpoint() throws Exception {
|
void incrementalEndpointBuildEnableSpecificEndpoint() throws Exception {
|
||||||
TestProject project = new TestProject(this.tempDir, SpecificEndpoint.class);
|
TestProject project = new TestProject(SpecificEndpoint.class);
|
||||||
ConfigurationMetadata metadata = project.fullBuild();
|
ConfigurationMetadata metadata = project.compile();
|
||||||
assertThat(metadata).has(Metadata.withGroup("management.endpoint.specific").fromSource(SpecificEndpoint.class));
|
assertThat(metadata).has(Metadata.withGroup("management.endpoint.specific").fromSource(SpecificEndpoint.class));
|
||||||
assertThat(metadata).has(enabledFlag("specific", true));
|
assertThat(metadata).has(enabledFlag("specific", true));
|
||||||
assertThat(metadata).has(cacheTtl("specific"));
|
assertThat(metadata).has(cacheTtl("specific"));
|
||||||
assertThat(metadata.getItems()).hasSize(3);
|
assertThat(metadata.getItems()).hasSize(3);
|
||||||
project.replaceText(SpecificEndpoint.class, "enableByDefault = true", "enableByDefault = false");
|
project.replaceText(SpecificEndpoint.class, "enableByDefault = true", "enableByDefault = false");
|
||||||
metadata = project.incrementalBuild(SpecificEndpoint.class);
|
metadata = project.compile();
|
||||||
assertThat(metadata).has(Metadata.withGroup("management.endpoint.specific").fromSource(SpecificEndpoint.class));
|
assertThat(metadata).has(Metadata.withGroup("management.endpoint.specific").fromSource(SpecificEndpoint.class));
|
||||||
assertThat(metadata).has(enabledFlag("specific", false));
|
assertThat(metadata).has(enabledFlag("specific", false));
|
||||||
assertThat(metadata).has(cacheTtl("specific"));
|
assertThat(metadata).has(cacheTtl("specific"));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2021 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -32,31 +32,30 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* Metadata generation tests for incremental builds.
|
* Metadata generation tests for incremental builds.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
class IncrementalBuildMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
class IncrementalBuildMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void incrementalBuild() throws Exception {
|
void incrementalBuild() throws Exception {
|
||||||
TestProject project = new TestProject(this.tempDir, FooProperties.class, BarProperties.class);
|
TestProject project = new TestProject(FooProperties.class, BarProperties.class);
|
||||||
assertThat(project.getOutputFile(MetadataStore.METADATA_PATH).exists()).isFalse();
|
ConfigurationMetadata metadata = project.compile();
|
||||||
ConfigurationMetadata metadata = project.fullBuild();
|
|
||||||
assertThat(project.getOutputFile(MetadataStore.METADATA_PATH).exists()).isTrue();
|
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withProperty("foo.counter").fromSource(FooProperties.class).withDefaultValue(0));
|
.has(Metadata.withProperty("foo.counter").fromSource(FooProperties.class).withDefaultValue(0));
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withProperty("bar.counter").fromSource(BarProperties.class).withDefaultValue(0));
|
.has(Metadata.withProperty("bar.counter").fromSource(BarProperties.class).withDefaultValue(0));
|
||||||
metadata = project.incrementalBuild(BarProperties.class);
|
metadata = project.compile();
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withProperty("foo.counter").fromSource(FooProperties.class).withDefaultValue(0));
|
.has(Metadata.withProperty("foo.counter").fromSource(FooProperties.class).withDefaultValue(0));
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withProperty("bar.counter").fromSource(BarProperties.class).withDefaultValue(0));
|
.has(Metadata.withProperty("bar.counter").fromSource(BarProperties.class).withDefaultValue(0));
|
||||||
project.addSourceCode(BarProperties.class, BarProperties.class.getResourceAsStream("BarProperties.snippet"));
|
project.addSourceCode(BarProperties.class, BarProperties.class.getResourceAsStream("BarProperties.snippet"));
|
||||||
metadata = project.incrementalBuild(BarProperties.class);
|
metadata = project.compile();
|
||||||
assertThat(metadata).has(Metadata.withProperty("bar.extra"));
|
assertThat(metadata).has(Metadata.withProperty("bar.extra"));
|
||||||
assertThat(metadata).has(Metadata.withProperty("foo.counter").withDefaultValue(0));
|
assertThat(metadata).has(Metadata.withProperty("foo.counter").withDefaultValue(0));
|
||||||
assertThat(metadata).has(Metadata.withProperty("bar.counter").withDefaultValue(0));
|
assertThat(metadata).has(Metadata.withProperty("bar.counter").withDefaultValue(0));
|
||||||
project.revert(BarProperties.class);
|
project.revert(BarProperties.class);
|
||||||
metadata = project.incrementalBuild(BarProperties.class);
|
metadata = project.compile();
|
||||||
assertThat(metadata).isNotEqualTo(Metadata.withProperty("bar.extra"));
|
assertThat(metadata).isNotEqualTo(Metadata.withProperty("bar.extra"));
|
||||||
assertThat(metadata).has(Metadata.withProperty("foo.counter").withDefaultValue(0));
|
assertThat(metadata).has(Metadata.withProperty("foo.counter").withDefaultValue(0));
|
||||||
assertThat(metadata).has(Metadata.withProperty("bar.counter").withDefaultValue(0));
|
assertThat(metadata).has(Metadata.withProperty("bar.counter").withDefaultValue(0));
|
||||||
|
|
@ -64,20 +63,21 @@ class IncrementalBuildMetadataGenerationTests extends AbstractMetadataGeneration
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void incrementalBuildAnnotationRemoved() throws Exception {
|
void incrementalBuildAnnotationRemoved() throws Exception {
|
||||||
TestProject project = new TestProject(this.tempDir, FooProperties.class, BarProperties.class);
|
TestProject project = new TestProject(FooProperties.class, BarProperties.class);
|
||||||
ConfigurationMetadata metadata = project.fullBuild();
|
ConfigurationMetadata metadata = project.compile();
|
||||||
assertThat(metadata).has(Metadata.withProperty("foo.counter").withDefaultValue(0));
|
assertThat(metadata).has(Metadata.withProperty("foo.counter").withDefaultValue(0));
|
||||||
assertThat(metadata).has(Metadata.withProperty("bar.counter").withDefaultValue(0));
|
assertThat(metadata).has(Metadata.withProperty("bar.counter").withDefaultValue(0));
|
||||||
project.replaceText(BarProperties.class, "@ConfigurationProperties", "//@ConfigurationProperties");
|
project.replaceText(BarProperties.class, "@ConfigurationProperties", "//@ConfigurationProperties");
|
||||||
metadata = project.incrementalBuild(BarProperties.class);
|
project.replaceText(FooProperties.class, "@ConfigurationProperties", "//@ConfigurationProperties");
|
||||||
|
metadata = project.compile();
|
||||||
assertThat(metadata).isNull();
|
assertThat(metadata).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled("gh-26271")
|
@Disabled("gh-26271")
|
||||||
void incrementalBuildTypeRenamed() throws Exception {
|
void incrementalBuildTypeRenamed() throws Exception {
|
||||||
TestProject project = new TestProject(this.tempDir, FooProperties.class, BarProperties.class);
|
TestProject project = new TestProject(FooProperties.class, BarProperties.class);
|
||||||
ConfigurationMetadata metadata = project.fullBuild();
|
ConfigurationMetadata metadata = project.compile();
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withProperty("foo.counter").fromSource(FooProperties.class).withDefaultValue(0));
|
.has(Metadata.withProperty("foo.counter").fromSource(FooProperties.class).withDefaultValue(0));
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
|
|
@ -85,7 +85,7 @@ class IncrementalBuildMetadataGenerationTests extends AbstractMetadataGeneration
|
||||||
assertThat(metadata).doesNotHave(Metadata.withProperty("bar.counter").fromSource(RenamedBarProperties.class));
|
assertThat(metadata).doesNotHave(Metadata.withProperty("bar.counter").fromSource(RenamedBarProperties.class));
|
||||||
project.delete(BarProperties.class);
|
project.delete(BarProperties.class);
|
||||||
project.add(RenamedBarProperties.class);
|
project.add(RenamedBarProperties.class);
|
||||||
metadata = project.incrementalBuild(RenamedBarProperties.class);
|
metadata = project.compile();
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
.has(Metadata.withProperty("foo.counter").fromSource(FooProperties.class).withDefaultValue(0));
|
.has(Metadata.withProperty("foo.counter").fromSource(FooProperties.class).withDefaultValue(0));
|
||||||
assertThat(metadata)
|
assertThat(metadata)
|
||||||
|
|
@ -96,9 +96,9 @@ class IncrementalBuildMetadataGenerationTests extends AbstractMetadataGeneration
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void incrementalBuildDoesNotDeleteItems() throws Exception {
|
void incrementalBuildDoesNotDeleteItems() throws Exception {
|
||||||
TestProject project = new TestProject(this.tempDir, ClassWithNestedProperties.class, FooProperties.class);
|
TestProject project = new TestProject(ClassWithNestedProperties.class, FooProperties.class);
|
||||||
ConfigurationMetadata initialMetadata = project.fullBuild();
|
ConfigurationMetadata initialMetadata = project.compile();
|
||||||
ConfigurationMetadata updatedMetadata = project.incrementalBuild(FooProperties.class);
|
ConfigurationMetadata updatedMetadata = project.compile();
|
||||||
assertThat(initialMetadata.getItems()).isEqualTo(updatedMetadata.getItems());
|
assertThat(initialMetadata.getItems()).isEqualTo(updatedMetadata.getItems());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.boot.configurationprocessor;
|
package org.springframework.boot.configurationprocessor;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -37,15 +35,16 @@ import org.springframework.boot.configurationprocessor.metadata.TestJsonConverte
|
||||||
import org.springframework.boot.configurationsample.simple.DeprecatedSingleProperty;
|
import org.springframework.boot.configurationsample.simple.DeprecatedSingleProperty;
|
||||||
import org.springframework.boot.configurationsample.simple.SimpleProperties;
|
import org.springframework.boot.configurationsample.simple.SimpleProperties;
|
||||||
import org.springframework.boot.configurationsample.specific.SimpleConflictingProperties;
|
import org.springframework.boot.configurationsample.specific.SimpleConflictingProperties;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.core.test.tools.CompilationException;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata generation tests for merging additional metadata.
|
* Metadata generation tests for merging additional metadata.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
|
|
@ -53,8 +52,8 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
void mergingOfAdditionalProperty() throws Exception {
|
void mergingOfAdditionalProperty() throws Exception {
|
||||||
ItemMetadata property = ItemMetadata.newProperty(null, "foo", "java.lang.String",
|
ItemMetadata property = ItemMetadata.newProperty(null, "foo", "java.lang.String",
|
||||||
AdditionalMetadata.class.getName(), null, null, null, null);
|
AdditionalMetadata.class.getName(), null, null, null, null);
|
||||||
writeAdditionalMetadata(property);
|
String additionalMetadata = buildAdditionalMetadata(property);
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
ConfigurationMetadata metadata = compile(additionalMetadata, SimpleProperties.class);
|
||||||
assertThat(metadata).has(Metadata.withProperty("simple.comparator"));
|
assertThat(metadata).has(Metadata.withProperty("simple.comparator"));
|
||||||
assertThat(metadata).has(Metadata.withProperty("foo", String.class).fromSource(AdditionalMetadata.class));
|
assertThat(metadata).has(Metadata.withProperty("foo", String.class).fromSource(AdditionalMetadata.class));
|
||||||
}
|
}
|
||||||
|
|
@ -63,8 +62,8 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
void mergingOfAdditionalPropertyMatchingGroup() throws Exception {
|
void mergingOfAdditionalPropertyMatchingGroup() throws Exception {
|
||||||
ItemMetadata property = ItemMetadata.newProperty(null, "simple", "java.lang.String", null, null, null, null,
|
ItemMetadata property = ItemMetadata.newProperty(null, "simple", "java.lang.String", null, null, null, null,
|
||||||
null);
|
null);
|
||||||
writeAdditionalMetadata(property);
|
String additionalMetadata = buildAdditionalMetadata(property);
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
ConfigurationMetadata metadata = compile(additionalMetadata, SimpleProperties.class);
|
||||||
assertThat(metadata).has(Metadata.withGroup("simple").fromSource(SimpleProperties.class));
|
assertThat(metadata).has(Metadata.withGroup("simple").fromSource(SimpleProperties.class));
|
||||||
assertThat(metadata).has(Metadata.withProperty("simple", String.class));
|
assertThat(metadata).has(Metadata.withProperty("simple", String.class));
|
||||||
}
|
}
|
||||||
|
|
@ -72,8 +71,8 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
@Test
|
@Test
|
||||||
void mergeExistingPropertyDefaultValue() throws Exception {
|
void mergeExistingPropertyDefaultValue() throws Exception {
|
||||||
ItemMetadata property = ItemMetadata.newProperty("simple", "flag", null, null, null, null, true, null);
|
ItemMetadata property = ItemMetadata.newProperty("simple", "flag", null, null, null, null, true, null);
|
||||||
writeAdditionalMetadata(property);
|
String additionalMetadata = buildAdditionalMetadata(property);
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
ConfigurationMetadata metadata = compile(additionalMetadata, SimpleProperties.class);
|
||||||
assertThat(metadata).has(Metadata.withProperty("simple.flag", Boolean.class).fromSource(SimpleProperties.class)
|
assertThat(metadata).has(Metadata.withProperty("simple.flag", Boolean.class).fromSource(SimpleProperties.class)
|
||||||
.withDescription("A simple flag.").withDeprecation(null, null).withDefaultValue(true));
|
.withDescription("A simple flag.").withDeprecation(null, null).withDefaultValue(true));
|
||||||
assertThat(metadata.getItems()).hasSize(4);
|
assertThat(metadata.getItems()).hasSize(4);
|
||||||
|
|
@ -83,8 +82,9 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
void mergeExistingPropertyWithSeveralCandidates() throws Exception {
|
void mergeExistingPropertyWithSeveralCandidates() throws Exception {
|
||||||
ItemMetadata property = ItemMetadata.newProperty("simple", "flag", Boolean.class.getName(), null, null, null,
|
ItemMetadata property = ItemMetadata.newProperty("simple", "flag", Boolean.class.getName(), null, null, null,
|
||||||
true, null);
|
true, null);
|
||||||
writeAdditionalMetadata(property);
|
String additionalMetadata = buildAdditionalMetadata(property);
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class, SimpleConflictingProperties.class);
|
ConfigurationMetadata metadata = compile(additionalMetadata, SimpleProperties.class,
|
||||||
|
SimpleConflictingProperties.class);
|
||||||
assertThat(metadata.getItems()).hasSize(6);
|
assertThat(metadata.getItems()).hasSize(6);
|
||||||
List<ItemMetadata> items = metadata.getItems().stream().filter((item) -> item.getName().equals("simple.flag"))
|
List<ItemMetadata> items = metadata.getItems().stream().filter((item) -> item.getName().equals("simple.flag"))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
@ -107,8 +107,8 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
void mergeExistingPropertyDescription() throws Exception {
|
void mergeExistingPropertyDescription() throws Exception {
|
||||||
ItemMetadata property = ItemMetadata.newProperty("simple", "comparator", null, null, null, "A nice comparator.",
|
ItemMetadata property = ItemMetadata.newProperty("simple", "comparator", null, null, null, "A nice comparator.",
|
||||||
null, null);
|
null, null);
|
||||||
writeAdditionalMetadata(property);
|
String additionalMetadata = buildAdditionalMetadata(property);
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
ConfigurationMetadata metadata = compile(additionalMetadata, SimpleProperties.class);
|
||||||
assertThat(metadata).has(Metadata.withProperty("simple.comparator", "java.util.Comparator<?>")
|
assertThat(metadata).has(Metadata.withProperty("simple.comparator", "java.util.Comparator<?>")
|
||||||
.fromSource(SimpleProperties.class).withDescription("A nice comparator."));
|
.fromSource(SimpleProperties.class).withDescription("A nice comparator."));
|
||||||
assertThat(metadata.getItems()).hasSize(4);
|
assertThat(metadata.getItems()).hasSize(4);
|
||||||
|
|
@ -118,8 +118,8 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
void mergeExistingPropertyDeprecation() throws Exception {
|
void mergeExistingPropertyDeprecation() throws Exception {
|
||||||
ItemMetadata property = ItemMetadata.newProperty("simple", "comparator", null, null, null, null, null,
|
ItemMetadata property = ItemMetadata.newProperty("simple", "comparator", null, null, null, null, null,
|
||||||
new ItemDeprecation("Don't use this.", "simple.complex-comparator", "error"));
|
new ItemDeprecation("Don't use this.", "simple.complex-comparator", "error"));
|
||||||
writeAdditionalMetadata(property);
|
String additionalMetadata = buildAdditionalMetadata(property);
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
ConfigurationMetadata metadata = compile(additionalMetadata, SimpleProperties.class);
|
||||||
assertThat(metadata).has(
|
assertThat(metadata).has(
|
||||||
Metadata.withProperty("simple.comparator", "java.util.Comparator<?>").fromSource(SimpleProperties.class)
|
Metadata.withProperty("simple.comparator", "java.util.Comparator<?>").fromSource(SimpleProperties.class)
|
||||||
.withDeprecation("Don't use this.", "simple.complex-comparator", "error"));
|
.withDeprecation("Don't use this.", "simple.complex-comparator", "error"));
|
||||||
|
|
@ -130,8 +130,8 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
void mergeExistingPropertyDeprecationOverride() throws Exception {
|
void mergeExistingPropertyDeprecationOverride() throws Exception {
|
||||||
ItemMetadata property = ItemMetadata.newProperty("singledeprecated", "name", null, null, null, null, null,
|
ItemMetadata property = ItemMetadata.newProperty("singledeprecated", "name", null, null, null, null, null,
|
||||||
new ItemDeprecation("Don't use this.", "single.name"));
|
new ItemDeprecation("Don't use this.", "single.name"));
|
||||||
writeAdditionalMetadata(property);
|
String additionalMetadata = buildAdditionalMetadata(property);
|
||||||
ConfigurationMetadata metadata = compile(DeprecatedSingleProperty.class);
|
ConfigurationMetadata metadata = compile(additionalMetadata, DeprecatedSingleProperty.class);
|
||||||
assertThat(metadata).has(Metadata.withProperty("singledeprecated.name", String.class.getName())
|
assertThat(metadata).has(Metadata.withProperty("singledeprecated.name", String.class.getName())
|
||||||
.fromSource(DeprecatedSingleProperty.class).withDeprecation("Don't use this.", "single.name"));
|
.fromSource(DeprecatedSingleProperty.class).withDeprecation("Don't use this.", "single.name"));
|
||||||
assertThat(metadata.getItems()).hasSize(3);
|
assertThat(metadata.getItems()).hasSize(3);
|
||||||
|
|
@ -141,8 +141,8 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
void mergeExistingPropertyDeprecationOverrideLevel() throws Exception {
|
void mergeExistingPropertyDeprecationOverrideLevel() throws Exception {
|
||||||
ItemMetadata property = ItemMetadata.newProperty("singledeprecated", "name", null, null, null, null, null,
|
ItemMetadata property = ItemMetadata.newProperty("singledeprecated", "name", null, null, null, null, null,
|
||||||
new ItemDeprecation(null, null, "error"));
|
new ItemDeprecation(null, null, "error"));
|
||||||
writeAdditionalMetadata(property);
|
String additionalMetadata = buildAdditionalMetadata(property);
|
||||||
ConfigurationMetadata metadata = compile(DeprecatedSingleProperty.class);
|
ConfigurationMetadata metadata = compile(additionalMetadata, DeprecatedSingleProperty.class);
|
||||||
assertThat(metadata).has(Metadata.withProperty("singledeprecated.name", String.class.getName())
|
assertThat(metadata).has(Metadata.withProperty("singledeprecated.name", String.class.getName())
|
||||||
.fromSource(DeprecatedSingleProperty.class)
|
.fromSource(DeprecatedSingleProperty.class)
|
||||||
.withDeprecation("renamed", "singledeprecated.new-name", "error"));
|
.withDeprecation("renamed", "singledeprecated.new-name", "error"));
|
||||||
|
|
@ -151,17 +151,17 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void mergeOfInvalidAdditionalMetadata() throws IOException {
|
void mergeOfInvalidAdditionalMetadata() throws IOException {
|
||||||
File additionalMetadataFile = createAdditionalMetadataFile();
|
String metadata = "Hello World";
|
||||||
FileCopyUtils.copy("Hello World", new FileWriter(additionalMetadataFile));
|
assertThatExceptionOfType(CompilationException.class)
|
||||||
assertThatIllegalStateException().isThrownBy(() -> compile(SimpleProperties.class))
|
.isThrownBy(() -> compile(metadata, SimpleProperties.class))
|
||||||
.withMessage("Compilation failed");
|
.withMessageContaining("Invalid additional meta-data");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void mergingOfSimpleHint() throws Exception {
|
void mergingOfSimpleHint() throws Exception {
|
||||||
writeAdditionalHints(ItemHint.newHint("simple.the-name", new ItemHint.ValueHint("boot", "Bla bla"),
|
String hints = buildAdditionalHints(ItemHint.newHint("simple.the-name",
|
||||||
new ItemHint.ValueHint("spring", null)));
|
new ItemHint.ValueHint("boot", "Bla bla"), new ItemHint.ValueHint("spring", null)));
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
ConfigurationMetadata metadata = compile(hints, SimpleProperties.class);
|
||||||
assertThat(metadata).has(Metadata.withProperty("simple.the-name", String.class)
|
assertThat(metadata).has(Metadata.withProperty("simple.the-name", String.class)
|
||||||
.fromSource(SimpleProperties.class).withDescription("The name of this simple properties.")
|
.fromSource(SimpleProperties.class).withDescription("The name of this simple properties.")
|
||||||
.withDefaultValue("boot").withDeprecation(null, null));
|
.withDefaultValue("boot").withDeprecation(null, null));
|
||||||
|
|
@ -171,8 +171,9 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void mergingOfHintWithNonCanonicalName() throws Exception {
|
void mergingOfHintWithNonCanonicalName() throws Exception {
|
||||||
writeAdditionalHints(ItemHint.newHint("simple.theName", new ItemHint.ValueHint("boot", "Bla bla")));
|
String hints = buildAdditionalHints(
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
ItemHint.newHint("simple.theName", new ItemHint.ValueHint("boot", "Bla bla")));
|
||||||
|
ConfigurationMetadata metadata = compile(hints, SimpleProperties.class);
|
||||||
assertThat(metadata).has(Metadata.withProperty("simple.the-name", String.class)
|
assertThat(metadata).has(Metadata.withProperty("simple.the-name", String.class)
|
||||||
.fromSource(SimpleProperties.class).withDescription("The name of this simple properties.")
|
.fromSource(SimpleProperties.class).withDescription("The name of this simple properties.")
|
||||||
.withDefaultValue("boot").withDeprecation(null, null));
|
.withDefaultValue("boot").withDeprecation(null, null));
|
||||||
|
|
@ -181,10 +182,10 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void mergingOfHintWithProvider() throws Exception {
|
void mergingOfHintWithProvider() throws Exception {
|
||||||
writeAdditionalHints(new ItemHint("simple.theName", Collections.emptyList(),
|
String hints = buildAdditionalHints(new ItemHint("simple.theName", Collections.emptyList(),
|
||||||
Arrays.asList(new ItemHint.ValueProvider("first", Collections.singletonMap("target", "org.foo")),
|
Arrays.asList(new ItemHint.ValueProvider("first", Collections.singletonMap("target", "org.foo")),
|
||||||
new ItemHint.ValueProvider("second", null))));
|
new ItemHint.ValueProvider("second", null))));
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
ConfigurationMetadata metadata = compile(hints, SimpleProperties.class);
|
||||||
assertThat(metadata).has(Metadata.withProperty("simple.the-name", String.class)
|
assertThat(metadata).has(Metadata.withProperty("simple.the-name", String.class)
|
||||||
.fromSource(SimpleProperties.class).withDescription("The name of this simple properties.")
|
.fromSource(SimpleProperties.class).withDescription("The name of this simple properties.")
|
||||||
.withDefaultValue("boot").withDeprecation(null, null));
|
.withDefaultValue("boot").withDeprecation(null, null));
|
||||||
|
|
@ -194,58 +195,48 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void mergingOfAdditionalDeprecation() throws Exception {
|
void mergingOfAdditionalDeprecation() throws Exception {
|
||||||
writePropertyDeprecation(ItemMetadata.newProperty("simple", "wrongName", "java.lang.String", null, null, null,
|
String deprecations = buildPropertyDeprecations(ItemMetadata.newProperty("simple", "wrongName",
|
||||||
null, new ItemDeprecation("Lame name.", "simple.the-name")));
|
"java.lang.String", null, null, null, null, new ItemDeprecation("Lame name.", "simple.the-name")));
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
ConfigurationMetadata metadata = compile(deprecations, SimpleProperties.class);
|
||||||
assertThat(metadata).has(Metadata.withProperty("simple.wrong-name", String.class).withDeprecation("Lame name.",
|
assertThat(metadata).has(Metadata.withProperty("simple.wrong-name", String.class).withDeprecation("Lame name.",
|
||||||
"simple.the-name"));
|
"simple.the-name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void mergingOfAdditionalMetadata() throws Exception {
|
void mergingOfAdditionalMetadata() throws Exception {
|
||||||
File metaInfDirectory = new File(getCompiler().getOutputLocation(), "META-INF");
|
|
||||||
metaInfDirectory.mkdirs();
|
|
||||||
File additionalMetadataFile = new File(metaInfDirectory, "additional-spring-configuration-metadata.json");
|
|
||||||
additionalMetadataFile.createNewFile();
|
|
||||||
JSONObject property = new JSONObject();
|
JSONObject property = new JSONObject();
|
||||||
property.put("name", "foo");
|
property.put("name", "foo");
|
||||||
property.put("type", "java.lang.String");
|
property.put("type", "java.lang.String");
|
||||||
property.put("sourceType", AdditionalMetadata.class.getName());
|
property.put("sourceType", AdditionalMetadata.class.getName());
|
||||||
JSONArray properties = new JSONArray();
|
JSONArray properties = new JSONArray();
|
||||||
properties.put(property);
|
properties.put(property);
|
||||||
JSONObject additionalMetadata = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
additionalMetadata.put("properties", properties);
|
json.put("properties", properties);
|
||||||
FileWriter writer = new FileWriter(additionalMetadataFile);
|
String additionalMetadata = json.toString();
|
||||||
writer.append(additionalMetadata.toString(2));
|
ConfigurationMetadata metadata = compile(additionalMetadata, SimpleProperties.class);
|
||||||
writer.flush();
|
|
||||||
writer.close();
|
|
||||||
ConfigurationMetadata metadata = compile(SimpleProperties.class);
|
|
||||||
assertThat(metadata).has(Metadata.withProperty("simple.comparator"));
|
assertThat(metadata).has(Metadata.withProperty("simple.comparator"));
|
||||||
assertThat(metadata).has(Metadata.withProperty("foo", String.class).fromSource(AdditionalMetadata.class));
|
assertThat(metadata).has(Metadata.withProperty("foo", String.class).fromSource(AdditionalMetadata.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeAdditionalMetadata(ItemMetadata... metadata) throws Exception {
|
private String buildAdditionalMetadata(ItemMetadata... metadata) throws Exception {
|
||||||
TestJsonConverter converter = new TestJsonConverter();
|
TestJsonConverter converter = new TestJsonConverter();
|
||||||
File additionalMetadataFile = createAdditionalMetadataFile();
|
|
||||||
JSONObject additionalMetadata = new JSONObject();
|
JSONObject additionalMetadata = new JSONObject();
|
||||||
JSONArray properties = new JSONArray();
|
JSONArray properties = new JSONArray();
|
||||||
for (ItemMetadata itemMetadata : metadata) {
|
for (ItemMetadata itemMetadata : metadata) {
|
||||||
properties.put(converter.toJsonObject(itemMetadata));
|
properties.put(converter.toJsonObject(itemMetadata));
|
||||||
}
|
}
|
||||||
additionalMetadata.put("properties", properties);
|
additionalMetadata.put("properties", properties);
|
||||||
writeMetadata(additionalMetadataFile, additionalMetadata);
|
return additionalMetadata.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeAdditionalHints(ItemHint... hints) throws Exception {
|
private String buildAdditionalHints(ItemHint... hints) throws Exception {
|
||||||
TestJsonConverter converter = new TestJsonConverter();
|
TestJsonConverter converter = new TestJsonConverter();
|
||||||
File additionalMetadataFile = createAdditionalMetadataFile();
|
|
||||||
JSONObject additionalMetadata = new JSONObject();
|
JSONObject additionalMetadata = new JSONObject();
|
||||||
additionalMetadata.put("hints", converter.toJsonArray(Arrays.asList(hints)));
|
additionalMetadata.put("hints", converter.toJsonArray(Arrays.asList(hints)));
|
||||||
writeMetadata(additionalMetadataFile, additionalMetadata);
|
return additionalMetadata.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writePropertyDeprecation(ItemMetadata... items) throws Exception {
|
private String buildPropertyDeprecations(ItemMetadata... items) throws Exception {
|
||||||
File additionalMetadataFile = createAdditionalMetadataFile();
|
|
||||||
JSONArray propertiesArray = new JSONArray();
|
JSONArray propertiesArray = new JSONArray();
|
||||||
for (ItemMetadata item : items) {
|
for (ItemMetadata item : items) {
|
||||||
JSONObject jsonObject = new JSONObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
|
@ -269,21 +260,7 @@ class MergeMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
}
|
}
|
||||||
JSONObject additionalMetadata = new JSONObject();
|
JSONObject additionalMetadata = new JSONObject();
|
||||||
additionalMetadata.put("properties", propertiesArray);
|
additionalMetadata.put("properties", propertiesArray);
|
||||||
writeMetadata(additionalMetadataFile, additionalMetadata);
|
return additionalMetadata.toString();
|
||||||
}
|
|
||||||
|
|
||||||
private File createAdditionalMetadataFile() throws IOException {
|
|
||||||
File metaInfDirectory = new File(getCompiler().getOutputLocation(), "META-INF");
|
|
||||||
metaInfDirectory.mkdirs();
|
|
||||||
File additionalMetadataFile = new File(metaInfDirectory, "additional-spring-configuration-metadata.json");
|
|
||||||
additionalMetadataFile.createNewFile();
|
|
||||||
return additionalMetadataFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeMetadata(File metadataFile, JSONObject metadata) throws Exception {
|
|
||||||
try (FileWriter writer = new FileWriter(metadataFile)) {
|
|
||||||
writer.append(metadata.toString(2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AdditionalMetadata {
|
static class AdditionalMetadata {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -36,6 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* Metadata generation tests for types defined by {@code @Bean} methods.
|
* Metadata generation tests for types defined by {@code @Bean} methods.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
class MethodBasedMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
class MethodBasedMetadataGenerationTests extends AbstractMetadataGenerationTests {
|
||||||
|
|
||||||
|
|
@ -65,7 +66,7 @@ class MethodBasedMetadataGenerationTests extends AbstractMetadataGenerationTests
|
||||||
@Test
|
@Test
|
||||||
void privateMethodConfig() {
|
void privateMethodConfig() {
|
||||||
ConfigurationMetadata metadata = compile(PrivateMethodConfig.class);
|
ConfigurationMetadata metadata = compile(PrivateMethodConfig.class);
|
||||||
assertThat(metadata).doesNotHave(Metadata.withGroup("foo"));
|
assertThat(metadata).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.boot.configurationprocessor;
|
package org.springframework.boot.configurationprocessor;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
@ -29,7 +28,6 @@ import java.util.stream.Stream;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
|
||||||
|
|
||||||
import org.springframework.boot.configurationprocessor.metadata.ItemMetadata;
|
import org.springframework.boot.configurationprocessor.metadata.ItemMetadata;
|
||||||
import org.springframework.boot.configurationprocessor.test.RoundEnvironmentTester;
|
import org.springframework.boot.configurationprocessor.test.RoundEnvironmentTester;
|
||||||
|
|
@ -49,7 +47,8 @@ import org.springframework.boot.configurationsample.simple.HierarchicalPropertie
|
||||||
import org.springframework.boot.configurationsample.simple.HierarchicalPropertiesParent;
|
import org.springframework.boot.configurationsample.simple.HierarchicalPropertiesParent;
|
||||||
import org.springframework.boot.configurationsample.simple.SimpleProperties;
|
import org.springframework.boot.configurationsample.simple.SimpleProperties;
|
||||||
import org.springframework.boot.configurationsample.specific.TwoConstructorsExample;
|
import org.springframework.boot.configurationsample.specific.TwoConstructorsExample;
|
||||||
import org.springframework.boot.testsupport.compiler.TestCompiler;
|
import org.springframework.core.test.tools.SourceFile;
|
||||||
|
import org.springframework.core.test.tools.TestCompiler;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
@ -57,12 +56,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* Tests for {@link PropertyDescriptorResolver}.
|
* Tests for {@link PropertyDescriptorResolver}.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
class PropertyDescriptorResolverTests {
|
class PropertyDescriptorResolverTests {
|
||||||
|
|
||||||
@TempDir
|
|
||||||
File tempDir;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void propertiesWithJavaBeanProperties() throws IOException {
|
void propertiesWithJavaBeanProperties() throws IOException {
|
||||||
process(SimpleProperties.class,
|
process(SimpleProperties.class,
|
||||||
|
|
@ -181,7 +178,7 @@ class PropertyDescriptorResolverTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void process(Class<?> target, Collection<Class<?>> additionalClasses,
|
private void process(Class<?> target, Collection<Class<?>> additionalClasses,
|
||||||
BiConsumer<TypeElement, MetadataGenerationEnvironment> consumer) throws IOException {
|
BiConsumer<TypeElement, MetadataGenerationEnvironment> consumer) {
|
||||||
BiConsumer<RoundEnvironmentTester, MetadataGenerationEnvironment> internalConsumer = (roundEnv,
|
BiConsumer<RoundEnvironmentTester, MetadataGenerationEnvironment> internalConsumer = (roundEnv,
|
||||||
metadataEnv) -> {
|
metadataEnv) -> {
|
||||||
TypeElement element = roundEnv.getRootElement(target);
|
TypeElement element = roundEnv.getRootElement(target);
|
||||||
|
|
@ -189,11 +186,12 @@ class PropertyDescriptorResolverTests {
|
||||||
};
|
};
|
||||||
TestableAnnotationProcessor<MetadataGenerationEnvironment> processor = new TestableAnnotationProcessor<>(
|
TestableAnnotationProcessor<MetadataGenerationEnvironment> processor = new TestableAnnotationProcessor<>(
|
||||||
internalConsumer, new MetadataGenerationEnvironmentFactory());
|
internalConsumer, new MetadataGenerationEnvironmentFactory());
|
||||||
TestCompiler compiler = new TestCompiler(this.tempDir);
|
SourceFile targetSource = SourceFile.forTestClass(target);
|
||||||
ArrayList<Class<?>> allClasses = new ArrayList<>();
|
List<SourceFile> additionalSource = additionalClasses.stream().map(SourceFile::forTestClass).toList();
|
||||||
allClasses.add(target);
|
TestCompiler compiler = TestCompiler.forSystem().withProcessors(processor).withSources(targetSource)
|
||||||
allClasses.addAll(additionalClasses);
|
.withSources(additionalSource);
|
||||||
compiler.getTask(allClasses.toArray(new Class<?>[0])).call(processor);
|
compiler.compile((compiled) -> {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.boot.configurationprocessor;
|
package org.springframework.boot.configurationprocessor;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
|
|
@ -26,23 +24,20 @@ import javax.lang.model.element.TypeElement;
|
||||||
import javax.lang.model.element.VariableElement;
|
import javax.lang.model.element.VariableElement;
|
||||||
import javax.lang.model.util.ElementFilter;
|
import javax.lang.model.util.ElementFilter;
|
||||||
|
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
|
||||||
|
|
||||||
import org.springframework.boot.configurationprocessor.test.ItemMetadataAssert;
|
import org.springframework.boot.configurationprocessor.test.ItemMetadataAssert;
|
||||||
import org.springframework.boot.configurationprocessor.test.RoundEnvironmentTester;
|
import org.springframework.boot.configurationprocessor.test.RoundEnvironmentTester;
|
||||||
import org.springframework.boot.configurationprocessor.test.TestableAnnotationProcessor;
|
import org.springframework.boot.configurationprocessor.test.TestableAnnotationProcessor;
|
||||||
import org.springframework.boot.testsupport.compiler.TestCompiler;
|
import org.springframework.core.test.tools.SourceFile;
|
||||||
|
import org.springframework.core.test.tools.TestCompiler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base test infrastructure to test {@link PropertyDescriptor} implementations.
|
* Base test infrastructure to test {@link PropertyDescriptor} implementations.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
public abstract class PropertyDescriptorTests {
|
public abstract class PropertyDescriptorTests {
|
||||||
|
|
||||||
@TempDir
|
|
||||||
File tempDir;
|
|
||||||
|
|
||||||
protected String createAccessorMethodName(String prefix, String name) {
|
protected String createAccessorMethodName(String prefix, String name) {
|
||||||
char[] chars = name.toCharArray();
|
char[] chars = name.toCharArray();
|
||||||
chars[0] = Character.toUpperCase(chars[0]);
|
chars[0] = Character.toUpperCase(chars[0]);
|
||||||
|
|
@ -66,12 +61,14 @@ public abstract class PropertyDescriptorTests {
|
||||||
return new ItemMetadataAssert(property.resolveItemMetadata("test", metadataEnv));
|
return new ItemMetadataAssert(property.resolveItemMetadata("test", metadataEnv));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void process(Class<?> target, BiConsumer<RoundEnvironmentTester, MetadataGenerationEnvironment> consumer)
|
protected void process(Class<?> target,
|
||||||
throws IOException {
|
BiConsumer<RoundEnvironmentTester, MetadataGenerationEnvironment> consumer) {
|
||||||
TestableAnnotationProcessor<MetadataGenerationEnvironment> processor = new TestableAnnotationProcessor<>(
|
TestableAnnotationProcessor<MetadataGenerationEnvironment> processor = new TestableAnnotationProcessor<>(
|
||||||
consumer, new MetadataGenerationEnvironmentFactory());
|
consumer, new MetadataGenerationEnvironmentFactory());
|
||||||
TestCompiler compiler = new TestCompiler(this.tempDir);
|
TestCompiler compiler = TestCompiler.forSystem().withProcessors(processor)
|
||||||
compiler.getTask(target).call(processor);
|
.withSources(SourceFile.forTestClass(target));
|
||||||
|
compiler.compile((compiled) -> {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,27 +16,22 @@
|
||||||
|
|
||||||
package org.springframework.boot.configurationprocessor;
|
package org.springframework.boot.configurationprocessor;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.List;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
||||||
|
import org.springframework.boot.configurationprocessor.test.CompiledMetadataReader;
|
||||||
import org.springframework.boot.configurationprocessor.test.TestConfigurationMetadataAnnotationProcessor;
|
import org.springframework.boot.configurationprocessor.test.TestConfigurationMetadataAnnotationProcessor;
|
||||||
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||||
import org.springframework.boot.configurationsample.NestedConfigurationProperty;
|
import org.springframework.boot.configurationsample.NestedConfigurationProperty;
|
||||||
import org.springframework.boot.testsupport.compiler.TestCompiler;
|
import org.springframework.core.test.tools.SourceFile;
|
||||||
import org.springframework.boot.testsupport.compiler.TestCompiler.TestCompilationTask;
|
import org.springframework.core.test.tools.SourceFiles;
|
||||||
|
import org.springframework.core.test.tools.TestCompiler;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
import org.springframework.util.FileSystemUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A TestProject contains a copy of a subset of test sample code.
|
* A TestProject contains a copy of a subset of test sample code.
|
||||||
|
|
@ -46,85 +41,26 @@ import org.springframework.util.FileSystemUtils;
|
||||||
* original content itself.
|
* original content itself.
|
||||||
*
|
*
|
||||||
* @author Kris De Volder
|
* @author Kris De Volder
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
public class TestProject {
|
public class TestProject {
|
||||||
|
|
||||||
private static final Class<?>[] ALWAYS_INCLUDE = { ConfigurationProperties.class,
|
private static final Class<?>[] ALWAYS_INCLUDE = { ConfigurationProperties.class,
|
||||||
NestedConfigurationProperty.class };
|
NestedConfigurationProperty.class };
|
||||||
|
|
||||||
/**
|
private SourceFiles sources;
|
||||||
* Contains copies of the original source so we can modify it safely to test
|
|
||||||
* incremental builds.
|
|
||||||
*/
|
|
||||||
private File sourceDirectory;
|
|
||||||
|
|
||||||
private TestCompiler compiler;
|
public TestProject(Class<?>... classes) {
|
||||||
|
this.sources = SourceFiles.none().and(sourceFilesOf(ALWAYS_INCLUDE)).and(sourceFilesOf(classes));
|
||||||
private Set<File> sourceFiles = new LinkedHashSet<>();
|
|
||||||
|
|
||||||
public TestProject(File tempDirectory, Class<?>... classes) throws IOException {
|
|
||||||
this.sourceDirectory = new File(tempDirectory, "src");
|
|
||||||
this.compiler = new TestCompiler(new File(tempDirectory, "build")) {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected File getSourceDirectory() {
|
|
||||||
return TestProject.this.sourceDirectory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
public ConfigurationMetadata compile() {
|
||||||
Set<Class<?>> contents = new HashSet<>(Arrays.asList(classes));
|
TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor();
|
||||||
contents.addAll(Arrays.asList(ALWAYS_INCLUDE));
|
TestCompiler compiler = TestCompiler.forSystem().withProcessors(processor);
|
||||||
copySources(contents);
|
AtomicReference<ConfigurationMetadata> configurationMetadata = new AtomicReference<>();
|
||||||
}
|
compiler.compile(this.sources,
|
||||||
|
(compiled) -> configurationMetadata.set(CompiledMetadataReader.getMetadata(compiled)));
|
||||||
private void copySources(Set<Class<?>> contents) throws IOException {
|
return configurationMetadata.get();
|
||||||
for (Class<?> type : contents) {
|
|
||||||
copySources(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copySources(Class<?> type) throws IOException {
|
|
||||||
File original = getOriginalSourceFile(type);
|
|
||||||
File target = getSourceFile(type);
|
|
||||||
target.getParentFile().mkdirs();
|
|
||||||
FileCopyUtils.copy(original, target);
|
|
||||||
this.sourceFiles.add(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getSourceFile(Class<?> type) {
|
|
||||||
return new File(this.sourceDirectory, TestCompiler.sourcePathFor(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigurationMetadata fullBuild() {
|
|
||||||
TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor(
|
|
||||||
this.compiler.getOutputLocation());
|
|
||||||
TestCompilationTask task = this.compiler.getTask(this.sourceFiles);
|
|
||||||
deleteDirectoryContents(this.compiler.getOutputLocation());
|
|
||||||
task.call(processor);
|
|
||||||
return processor.getMetadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigurationMetadata incrementalBuild(Class<?>... toRecompile) {
|
|
||||||
TestConfigurationMetadataAnnotationProcessor processor = new TestConfigurationMetadataAnnotationProcessor(
|
|
||||||
this.compiler.getOutputLocation());
|
|
||||||
TestCompilationTask task = this.compiler.getTask(toRecompile);
|
|
||||||
task.call(processor);
|
|
||||||
return processor.getMetadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteDirectoryContents(File outputDirectory) {
|
|
||||||
FileSystemUtils.deleteRecursively(outputDirectory);
|
|
||||||
outputDirectory.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve File relative to project's output directory.
|
|
||||||
* @param relativePath the relative path
|
|
||||||
* @return the output file
|
|
||||||
*/
|
|
||||||
public File getOutputFile(String relativePath) {
|
|
||||||
Assert.isTrue(!new File(relativePath).isAbsolute(), "'" + relativePath + "' was absolute");
|
|
||||||
return new File(this.compiler.getOutputLocation(), relativePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -134,12 +70,12 @@ public class TestProject {
|
||||||
* @throws Exception if the source cannot be added
|
* @throws Exception if the source cannot be added
|
||||||
*/
|
*/
|
||||||
public void addSourceCode(Class<?> target, InputStream snippetStream) throws Exception {
|
public void addSourceCode(Class<?> target, InputStream snippetStream) throws Exception {
|
||||||
File targetFile = getSourceFile(target);
|
SourceFile sourceFile = SourceFile.forTestClass(target);
|
||||||
String contents = getContents(targetFile);
|
String contents = sourceFile.getContent();
|
||||||
int insertAt = contents.lastIndexOf('}');
|
int insertAt = contents.lastIndexOf('}');
|
||||||
String additionalSource = FileCopyUtils.copyToString(new InputStreamReader(snippetStream));
|
String additionalSource = FileCopyUtils.copyToString(new InputStreamReader(snippetStream));
|
||||||
contents = contents.substring(0, insertAt) + additionalSource + contents.substring(insertAt);
|
contents = contents.substring(0, insertAt) + additionalSource + contents.substring(insertAt);
|
||||||
putContents(targetFile, contents);
|
this.sources = this.sources.and(SourceFile.of(contents));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -147,53 +83,40 @@ public class TestProject {
|
||||||
* @param type the class to delete
|
* @param type the class to delete
|
||||||
*/
|
*/
|
||||||
public void delete(Class<?> type) {
|
public void delete(Class<?> type) {
|
||||||
File target = getSourceFile(type);
|
SourceFile[] newSources = this.sources.stream()
|
||||||
target.delete();
|
.filter((sourceFile) -> !sourceFile.getPath().equals(SourceFile.forTestClass(type).getPath()))
|
||||||
this.sourceFiles.remove(target);
|
.toArray(SourceFile[]::new);
|
||||||
|
this.sources = SourceFiles.of(newSources);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore source code of given class to its original contents.
|
* Restore source code of given class to its original contents.
|
||||||
* @param type the class to revert
|
* @param type the class to revert
|
||||||
* @throws IOException on IO error
|
|
||||||
*/
|
*/
|
||||||
public void revert(Class<?> type) throws IOException {
|
public void revert(Class<?> type) {
|
||||||
Assert.isTrue(getSourceFile(type).exists(), "Source file for type '" + type + "' does not exist");
|
Assert.isTrue(this.sources.stream().anyMatch((sourceFile) -> sourceFile.getClassName().equals(type.getName())),
|
||||||
copySources(type);
|
"Source file for type '" + type + "' does not exist");
|
||||||
|
this.sources = this.sources.and(SourceFile.forTestClass(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add source code of given class to this project.
|
* Add source code of given class to this project.
|
||||||
* @param type the class to add
|
* @param type the class to add
|
||||||
* @throws IOException on IO error
|
|
||||||
*/
|
*/
|
||||||
public void add(Class<?> type) throws IOException {
|
public void add(Class<?> type) {
|
||||||
Assert.isTrue(!getSourceFile(type).exists(), "Source file for type '" + type + "' already exists");
|
Assert.isTrue(this.sources.stream().noneMatch((sourceFile) -> sourceFile.getClassName().equals(type.getName())),
|
||||||
copySources(type);
|
"Source file for type '" + type + "' already exists");
|
||||||
|
this.sources = this.sources.and(SourceFile.forTestClass(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replaceText(Class<?> type, String find, String replace) throws Exception {
|
public void replaceText(Class<?> type, String find, String replace) {
|
||||||
File target = getSourceFile(type);
|
SourceFile sourceFile = SourceFile.forTestClass(type);
|
||||||
String contents = getContents(target);
|
String contents = sourceFile.getContent().replace(find, replace);
|
||||||
contents = contents.replace(find, replace);
|
this.sources = this.sources.and(SourceFile.of(contents));
|
||||||
putContents(target, contents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private List<SourceFile> sourceFilesOf(Class<?>... types) {
|
||||||
* Find the 'original' source code for given test class. Clients or subclasses should
|
return Arrays.stream(types).map(SourceFile::forTestClass).toList();
|
||||||
* have no need to know about these. They should work only with the copied source
|
|
||||||
* code.
|
|
||||||
*/
|
|
||||||
private File getOriginalSourceFile(Class<?> type) {
|
|
||||||
return new File(TestCompiler.SOURCE_DIRECTORY, TestCompiler.sourcePathFor(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void putContents(File targetFile, String contents) throws IOException {
|
|
||||||
FileCopyUtils.copy(new StringReader(contents), new FileWriter(targetFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getContents(File file) throws Exception {
|
|
||||||
return FileCopyUtils.copyToString(new FileReader(file));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,13 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.boot.configurationprocessor;
|
package org.springframework.boot.configurationprocessor;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
|
||||||
|
|
||||||
import org.springframework.boot.configurationprocessor.TypeUtils.TypeDescriptor;
|
import org.springframework.boot.configurationprocessor.TypeUtils.TypeDescriptor;
|
||||||
import org.springframework.boot.configurationprocessor.test.RoundEnvironmentTester;
|
import org.springframework.boot.configurationprocessor.test.RoundEnvironmentTester;
|
||||||
|
|
@ -30,7 +28,8 @@ import org.springframework.boot.configurationprocessor.test.TestableAnnotationPr
|
||||||
import org.springframework.boot.configurationsample.generic.AbstractGenericProperties;
|
import org.springframework.boot.configurationsample.generic.AbstractGenericProperties;
|
||||||
import org.springframework.boot.configurationsample.generic.AbstractIntermediateGenericProperties;
|
import org.springframework.boot.configurationsample.generic.AbstractIntermediateGenericProperties;
|
||||||
import org.springframework.boot.configurationsample.generic.SimpleGenericProperties;
|
import org.springframework.boot.configurationsample.generic.SimpleGenericProperties;
|
||||||
import org.springframework.boot.testsupport.compiler.TestCompiler;
|
import org.springframework.core.test.tools.SourceFile;
|
||||||
|
import org.springframework.core.test.tools.TestCompiler;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
@ -38,12 +37,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
* Tests for {@link TypeUtils}.
|
* Tests for {@link TypeUtils}.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
class TypeUtilsTests {
|
class TypeUtilsTests {
|
||||||
|
|
||||||
@TempDir
|
|
||||||
File tempDir;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void resolveTypeDescriptorOnConcreteClass() throws IOException {
|
void resolveTypeDescriptorOnConcreteClass() throws IOException {
|
||||||
process(SimpleGenericProperties.class, (roundEnv, typeUtils) -> {
|
process(SimpleGenericProperties.class, (roundEnv, typeUtils) -> {
|
||||||
|
|
@ -82,10 +79,12 @@ class TypeUtilsTests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void process(Class<?> target, BiConsumer<RoundEnvironmentTester, TypeUtils> consumer) throws IOException {
|
private void process(Class<?> target, BiConsumer<RoundEnvironmentTester, TypeUtils> consumer) {
|
||||||
TestableAnnotationProcessor<TypeUtils> processor = new TestableAnnotationProcessor<>(consumer, TypeUtils::new);
|
TestableAnnotationProcessor<TypeUtils> processor = new TestableAnnotationProcessor<>(consumer, TypeUtils::new);
|
||||||
TestCompiler compiler = new TestCompiler(this.tempDir);
|
TestCompiler compiler = TestCompiler.forSystem().withProcessors(processor)
|
||||||
compiler.getTask(target).call(processor);
|
.withSources(SourceFile.forTestClass(target));
|
||||||
|
compiler.compile((compiled) -> {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.boot.configurationprocessor.fieldvalues;
|
package org.springframework.boot.configurationprocessor.fieldvalues;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -31,10 +30,10 @@ import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
|
||||||
|
|
||||||
import org.springframework.boot.configurationsample.fieldvalues.FieldValues;
|
import org.springframework.boot.configurationsample.fieldvalues.FieldValues;
|
||||||
import org.springframework.boot.testsupport.compiler.TestCompiler;
|
import org.springframework.core.test.tools.SourceFile;
|
||||||
|
import org.springframework.core.test.tools.TestCompiler;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
|
@ -46,16 +45,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractFieldValuesProcessorTests {
|
public abstract class AbstractFieldValuesProcessorTests {
|
||||||
|
|
||||||
@TempDir
|
|
||||||
File tempDir;
|
|
||||||
|
|
||||||
protected abstract FieldValuesParser createProcessor(ProcessingEnvironment env);
|
protected abstract FieldValuesParser createProcessor(ProcessingEnvironment env);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getFieldValues() throws Exception {
|
void getFieldValues() throws Exception {
|
||||||
TestProcessor processor = new TestProcessor();
|
TestProcessor processor = new TestProcessor();
|
||||||
TestCompiler compiler = new TestCompiler(this.tempDir);
|
TestCompiler compiler = TestCompiler.forSystem().withProcessors(processor)
|
||||||
compiler.getTask(FieldValues.class).call(processor);
|
.withSources(SourceFile.forTestClass(FieldValues.class));
|
||||||
|
compiler.compile((compiled) -> {
|
||||||
|
});
|
||||||
Map<String, Object> values = processor.getValues();
|
Map<String, Object> values = processor.getValues();
|
||||||
assertThat(values.get("string")).isEqualTo("1");
|
assertThat(values.get("string")).isEqualTo("1");
|
||||||
assertThat(values.get("stringNone")).isNull();
|
assertThat(values.get("stringNone")).isNull();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2022 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.configurationprocessor.test;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
||||||
|
import org.springframework.boot.configurationprocessor.metadata.JsonMarshaller;
|
||||||
|
import org.springframework.core.test.tools.Compiled;
|
||||||
|
import org.springframework.core.test.tools.TestCompiler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the contents of metadata generated from the {@link TestCompiler}.
|
||||||
|
*
|
||||||
|
* @author Scott Frederick
|
||||||
|
*/
|
||||||
|
public final class CompiledMetadataReader {
|
||||||
|
|
||||||
|
private static final String METADATA_FILE = "META-INF/spring-configuration-metadata.json";
|
||||||
|
|
||||||
|
private CompiledMetadataReader() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConfigurationMetadata getMetadata(Compiled compiled) {
|
||||||
|
InputStream inputStream = compiled.getClassLoader().getResourceAsStream(METADATA_FILE);
|
||||||
|
try {
|
||||||
|
if (inputStream != null) {
|
||||||
|
return new JsonMarshaller().read(inputStream);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new RuntimeException("Failed to read metadata", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -16,10 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.boot.configurationprocessor.test;
|
package org.springframework.boot.configurationprocessor.test;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
@ -29,8 +25,6 @@ import javax.annotation.processing.SupportedSourceVersion;
|
||||||
import javax.lang.model.SourceVersion;
|
import javax.lang.model.SourceVersion;
|
||||||
|
|
||||||
import org.springframework.boot.configurationprocessor.ConfigurationMetadataAnnotationProcessor;
|
import org.springframework.boot.configurationprocessor.ConfigurationMetadataAnnotationProcessor;
|
||||||
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
|
||||||
import org.springframework.boot.configurationprocessor.metadata.JsonMarshaller;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test {@link ConfigurationMetadataAnnotationProcessor}.
|
* Test {@link ConfigurationMetadataAnnotationProcessor}.
|
||||||
|
|
@ -39,6 +33,7 @@ import org.springframework.boot.configurationprocessor.metadata.JsonMarshaller;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Kris De Volder
|
* @author Kris De Volder
|
||||||
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
@SupportedAnnotationTypes({ TestConfigurationMetadataAnnotationProcessor.CONFIGURATION_PROPERTIES_ANNOTATION,
|
@SupportedAnnotationTypes({ TestConfigurationMetadataAnnotationProcessor.CONFIGURATION_PROPERTIES_ANNOTATION,
|
||||||
TestConfigurationMetadataAnnotationProcessor.CONTROLLER_ENDPOINT_ANNOTATION,
|
TestConfigurationMetadataAnnotationProcessor.CONTROLLER_ENDPOINT_ANNOTATION,
|
||||||
|
|
@ -79,12 +74,7 @@ public class TestConfigurationMetadataAnnotationProcessor extends ConfigurationM
|
||||||
|
|
||||||
public static final String NAME_ANNOTATION = "org.springframework.boot.configurationsample.Name";
|
public static final String NAME_ANNOTATION = "org.springframework.boot.configurationsample.Name";
|
||||||
|
|
||||||
private ConfigurationMetadata metadata;
|
public TestConfigurationMetadataAnnotationProcessor() {
|
||||||
|
|
||||||
private final File outputLocation;
|
|
||||||
|
|
||||||
public TestConfigurationMetadataAnnotationProcessor(File outputLocation) {
|
|
||||||
this.outputLocation = outputLocation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -133,28 +123,4 @@ public class TestConfigurationMetadataAnnotationProcessor extends ConfigurationM
|
||||||
return NAME_ANNOTATION;
|
return NAME_ANNOTATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ConfigurationMetadata writeMetadata() throws Exception {
|
|
||||||
super.writeMetadata();
|
|
||||||
try {
|
|
||||||
File metadataFile = new File(this.outputLocation, "META-INF/spring-configuration-metadata.json");
|
|
||||||
if (metadataFile.isFile()) {
|
|
||||||
try (InputStream input = new FileInputStream(metadataFile)) {
|
|
||||||
this.metadata = new JsonMarshaller().read(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.metadata = new ConfigurationMetadata();
|
|
||||||
}
|
|
||||||
return this.metadata;
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
throw new RuntimeException("Failed to read metadata from disk", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigurationMetadata getMetadata() {
|
|
||||||
return this.metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ dependencies {
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
testImplementation("org.mockito:mockito-core")
|
testImplementation("org.mockito:mockito-core")
|
||||||
testImplementation("org.springframework:spring-test")
|
testImplementation("org.springframework:spring-test")
|
||||||
|
testImplementation("org.springframework:spring-core-test")
|
||||||
|
|
||||||
testRuntimeOnly("ch.qos.logback:logback-classic")
|
testRuntimeOnly("ch.qos.logback:logback-classic")
|
||||||
testRuntimeOnly("org.bouncycastle:bcprov-jdk18on:1.71")
|
testRuntimeOnly("org.bouncycastle:bcprov-jdk18on:1.71")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -101,6 +101,7 @@ class JarLauncherTests extends AbstractExecutableArchiveLauncherTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@SuppressWarnings("removal")
|
||||||
void explodedJarDefinedPackagesIncludeManifestAttributes() throws Exception {
|
void explodedJarDefinedPackagesIncludeManifestAttributes() throws Exception {
|
||||||
Manifest manifest = new Manifest();
|
Manifest manifest = new Manifest();
|
||||||
Attributes attributes = manifest.getMainAttributes();
|
Attributes attributes = manifest.getMainAttributes();
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ dependencies {
|
||||||
implementation("org.hamcrest:hamcrest-library")
|
implementation("org.hamcrest:hamcrest-library")
|
||||||
implementation("org.springframework:spring-core")
|
implementation("org.springframework:spring-core")
|
||||||
implementation("org.springframework:spring-test")
|
implementation("org.springframework:spring-test")
|
||||||
|
implementation("org.springframework:spring-core-test")
|
||||||
|
|
||||||
testImplementation("jakarta.servlet:jakarta.servlet-api")
|
testImplementation("jakarta.servlet:jakarta.servlet-api")
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -37,7 +37,10 @@ import javax.tools.ToolProvider;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @since 1.5.0
|
* @since 1.5.0
|
||||||
|
* @deprecated since 3.0.0 in favor of
|
||||||
|
* {@link org.springframework.core.test.tools.TestCompiler}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "3.0.0", forRemoval = true)
|
||||||
public class TestCompiler {
|
public class TestCompiler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ dependencies {
|
||||||
optional("org.jetbrains.kotlin:kotlin-stdlib")
|
optional("org.jetbrains.kotlin:kotlin-stdlib")
|
||||||
|
|
||||||
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
|
||||||
|
testImplementation("org.springframework:spring-core-test")
|
||||||
testImplementation("com.ibm.db2:jcc")
|
testImplementation("com.ibm.db2:jcc")
|
||||||
testImplementation("com.jayway.jsonpath:json-path")
|
testImplementation("com.jayway.jsonpath:json-path")
|
||||||
testImplementation("com.microsoft.sqlserver:mssql-jdbc")
|
testImplementation("com.microsoft.sqlserver:mssql-jdbc")
|
||||||
|
|
|
||||||
|
|
@ -16,36 +16,31 @@
|
||||||
|
|
||||||
package org.springframework.boot.context.properties.bind;
|
package org.springframework.boot.context.properties.bind;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
||||||
import org.springframework.boot.context.properties.source.MockConfigurationPropertySource;
|
import org.springframework.boot.context.properties.source.MockConfigurationPropertySource;
|
||||||
import org.springframework.boot.testsupport.compiler.TestCompiler;
|
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
|
import org.springframework.core.test.tools.SourceFile;
|
||||||
|
import org.springframework.core.test.tools.TestCompiler;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link ValueObjectBinder}.
|
* Tests for {@link ValueObjectBinder}.
|
||||||
|
|
@ -368,27 +363,28 @@ class ValueObjectBinderTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void bindToRecordWithDefaultValue(@TempDir File tempDir) throws IOException, ClassNotFoundException {
|
void bindToRecordWithDefaultValue() throws IOException {
|
||||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||||
source.put("test.record.property1", "value-from-config-1");
|
source.put("test.record.property1", "value-from-config-1");
|
||||||
this.sources.add(source);
|
this.sources.add(source);
|
||||||
File recordProperties = new File(tempDir, "RecordProperties.java");
|
String recordProperties = """
|
||||||
try (PrintWriter writer = new PrintWriter(new FileWriter(recordProperties))) {
|
public record RecordProperties(
|
||||||
writer.println("public record RecordProperties(");
|
@org.springframework.boot.context.properties.bind.DefaultValue("default-value-1") String property1,
|
||||||
writer.println(
|
@org.springframework.boot.context.properties.bind.DefaultValue("default-value-2") String property2) {
|
||||||
"@org.springframework.boot.context.properties.bind.DefaultValue(\"default-value-1\") String property1,");
|
|
||||||
writer.println(
|
|
||||||
"@org.springframework.boot.context.properties.bind.DefaultValue(\"default-value-2\") String property2");
|
|
||||||
writer.println(") {");
|
|
||||||
writer.println("}");
|
|
||||||
}
|
}
|
||||||
TestCompiler compiler = new TestCompiler(tempDir);
|
""";
|
||||||
compiler.getTask(Arrays.asList(recordProperties)).call();
|
TestCompiler.forSystem().withSources(SourceFile.of(recordProperties)).compile((compiled) -> {
|
||||||
ClassLoader ucl = new URLClassLoader(new URL[] { tempDir.toURI().toURL() });
|
try {
|
||||||
Object bean = this.binder.bind("test.record", Class.forName("RecordProperties", true, ucl)).get();
|
ClassLoader cl = compiled.getClassLoader();
|
||||||
|
Object bean = this.binder.bind("test.record", Class.forName("RecordProperties", true, cl)).get();
|
||||||
assertThat(bean).hasFieldOrPropertyWithValue("property1", "value-from-config-1")
|
assertThat(bean).hasFieldOrPropertyWithValue("property1", "value-from-config-1")
|
||||||
.hasFieldOrPropertyWithValue("property2", "default-value-2");
|
.hasFieldOrPropertyWithValue("property2", "default-value-2");
|
||||||
}
|
}
|
||||||
|
catch (ClassNotFoundException ex) {
|
||||||
|
fail("Expected generated class 'RecordProperties' not found", ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void noConfigurationProperty(BindException ex) {
|
private void noConfigurationProperty(BindException ex) {
|
||||||
assertThat(ex.getProperty()).isNull();
|
assertThat(ex.getProperty()).isNull();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue