13 changed files with 615 additions and 182 deletions
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
/* |
||||
* Copyright 2012-present 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.build.context.properties; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.util.List; |
||||
|
||||
import org.gradle.api.DefaultTask; |
||||
import org.gradle.api.file.RegularFileProperty; |
||||
import org.gradle.api.provider.ListProperty; |
||||
import org.gradle.api.provider.Property; |
||||
import org.gradle.api.tasks.Input; |
||||
import org.gradle.api.tasks.InputFile; |
||||
import org.gradle.api.tasks.OutputFile; |
||||
import org.gradle.api.tasks.PathSensitive; |
||||
import org.gradle.api.tasks.PathSensitivity; |
||||
import org.gradle.api.tasks.SourceTask; |
||||
import org.gradle.api.tasks.TaskAction; |
||||
import org.gradle.api.tasks.VerificationException; |
||||
|
||||
import org.springframework.boot.build.context.properties.ConfigurationPropertiesAnalyzer.Report; |
||||
|
||||
/** |
||||
* {@link SourceTask} that checks manual Spring configuration metadata files. |
||||
* |
||||
* @author Andy Wilkinson |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
public abstract class CheckManualSpringConfigurationMetadata extends DefaultTask { |
||||
|
||||
private final File projectDir; |
||||
|
||||
public CheckManualSpringConfigurationMetadata() { |
||||
this.projectDir = getProject().getProjectDir(); |
||||
} |
||||
|
||||
@OutputFile |
||||
public abstract RegularFileProperty getReportLocation(); |
||||
|
||||
@InputFile |
||||
@PathSensitive(PathSensitivity.RELATIVE) |
||||
public abstract Property<File> getMetadataLocation(); |
||||
|
||||
@Input |
||||
public abstract ListProperty<String> getExclusions(); |
||||
|
||||
@TaskAction |
||||
void check() throws IOException { |
||||
ConfigurationPropertiesAnalyzer analyzer = new ConfigurationPropertiesAnalyzer( |
||||
List.of(getMetadataLocation().get())); |
||||
Report report = new Report(this.projectDir); |
||||
analyzer.analyzeSort(report); |
||||
analyzer.analyzePropertyDescription(report, getExclusions().get()); |
||||
File reportFile = getReportLocation().get().getAsFile(); |
||||
report.write(reportFile); |
||||
if (report.hasProblems()) { |
||||
throw new VerificationException( |
||||
"Problems found in manual Spring configuration metadata. See " + reportFile + " for details."); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
/* |
||||
* Copyright 2012-present 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.build.context.properties; |
||||
|
||||
import java.io.File; |
||||
|
||||
import org.gradle.api.Plugin; |
||||
import org.gradle.api.Project; |
||||
import org.gradle.api.plugins.JavaPlugin; |
||||
import org.gradle.api.plugins.JavaPluginExtension; |
||||
import org.gradle.api.provider.Provider; |
||||
import org.gradle.api.tasks.SourceSet; |
||||
import org.gradle.api.tasks.TaskProvider; |
||||
import org.gradle.language.base.plugins.LifecycleBasePlugin; |
||||
import org.gradle.language.jvm.tasks.ProcessResources; |
||||
|
||||
/** |
||||
* {@link Plugin} for projects that <em>only</em> define manual configuration metadata. |
||||
* When applied, the plugin registers a {@link CheckManualSpringConfigurationMetadata} |
||||
* task and configures the {@code check} task to depend upon it. |
||||
* |
||||
* @author Andy Wilkinson |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
public class ConfigurationMetadataPlugin implements Plugin<Project> { |
||||
|
||||
/** |
||||
* Name of the {@link CheckAdditionalSpringConfigurationMetadata} task. |
||||
*/ |
||||
public static final String CHECK_MANUAL_SPRING_CONFIGURATION_METADATA_TASK_NAME = "checkManualSpringConfigurationMetadata"; |
||||
|
||||
@Override |
||||
public void apply(Project project) { |
||||
project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> registerCheckAdditionalMetadataTask(project)); |
||||
} |
||||
|
||||
private void registerCheckAdditionalMetadataTask(Project project) { |
||||
TaskProvider<CheckManualSpringConfigurationMetadata> checkConfigurationMetadata = project.getTasks() |
||||
.register(CHECK_MANUAL_SPRING_CONFIGURATION_METADATA_TASK_NAME, |
||||
CheckManualSpringConfigurationMetadata.class); |
||||
checkConfigurationMetadata.configure((check) -> { |
||||
SourceSet mainSourceSet = project.getExtensions() |
||||
.getByType(JavaPluginExtension.class) |
||||
.getSourceSets() |
||||
.getByName(SourceSet.MAIN_SOURCE_SET_NAME); |
||||
|
||||
Provider<File> manualMetadataLocation = project.getTasks() |
||||
.named(mainSourceSet.getProcessResourcesTaskName(), ProcessResources.class) |
||||
.map((processResources) -> new File(processResources.getDestinationDir(), |
||||
"META-INF/spring-configuration-metadata.json")); |
||||
check.getMetadataLocation().set(manualMetadataLocation); |
||||
check.getReportLocation() |
||||
.set(project.getLayout() |
||||
.getBuildDirectory() |
||||
.file("reports/manual-spring-configuration-metadata/check.txt")); |
||||
}); |
||||
project.getTasks() |
||||
.named(LifecycleBasePlugin.CHECK_TASK_NAME) |
||||
.configure((check) -> check.dependsOn(checkConfigurationMetadata)); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,252 @@
@@ -0,0 +1,252 @@
|
||||
/* |
||||
* Copyright 2012-present 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.build.context.properties; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.io.PrintWriter; |
||||
import java.io.StringWriter; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.StandardOpenOption; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.function.Consumer; |
||||
|
||||
import tools.jackson.core.StreamReadFeature; |
||||
import tools.jackson.databind.json.JsonMapper; |
||||
|
||||
import org.springframework.util.LinkedMultiValueMap; |
||||
import org.springframework.util.MultiValueMap; |
||||
import org.springframework.util.function.SingletonSupplier; |
||||
|
||||
/** |
||||
* Check configuration metadata for inconsistencies. The available checks are: |
||||
* <ul> |
||||
* <li>Metadata element should be sorted alphabetically: {@link #analyzeSort(Report)}</li> |
||||
* <li>Property must have a description: |
||||
* {@link #analyzePropertyDescription(Report, List)}</li> |
||||
* </ul> |
||||
* |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
class ConfigurationPropertiesAnalyzer { |
||||
|
||||
private final Collection<File> sources; |
||||
|
||||
private final SingletonSupplier<JsonMapper> jsonMapperSupplier; |
||||
|
||||
ConfigurationPropertiesAnalyzer(Collection<File> sources) { |
||||
if (sources.isEmpty()) { |
||||
throw new IllegalArgumentException("At least one source should be provided"); |
||||
} |
||||
this.sources = sources; |
||||
this.jsonMapperSupplier = SingletonSupplier |
||||
.of(() -> JsonMapper.builder().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION).build()); |
||||
} |
||||
|
||||
void analyzeSort(Report report) { |
||||
for (File source : this.sources) { |
||||
report.registerAnalysis(source, analyzeSort(source)); |
||||
} |
||||
} |
||||
|
||||
private Analysis analyzeSort(File source) { |
||||
Map<String, Object> json = readJsonContent(source); |
||||
Analysis analysis = new Analysis("Metadata element order:"); |
||||
analyzeMetadataElementsSort("groups", json, analysis); |
||||
analyzeMetadataElementsSort("properties", json, analysis); |
||||
analyzeMetadataElementsSort("hints", json, analysis); |
||||
return analysis; |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private void analyzeMetadataElementsSort(String key, Map<String, Object> json, Analysis analysis) { |
||||
List<Map<String, Object>> groups = (List<Map<String, Object>>) json.getOrDefault(key, Collections.emptyList()); |
||||
List<String> names = groups.stream().map((group) -> (String) group.get("name")).toList(); |
||||
List<String> sortedNames = names.stream().sorted().toList(); |
||||
for (int i = 0; i < names.size(); i++) { |
||||
String actual = names.get(i); |
||||
String expected = sortedNames.get(i); |
||||
if (!actual.equals(expected)) { |
||||
analysis.addItem("Wrong order at $." + key + "[" + i + "].name - expected '" + expected |
||||
+ "' but found '" + actual + "'"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void analyzePropertyDescription(Report report, List<String> exclusions) { |
||||
for (File source : this.sources) { |
||||
report.registerAnalysis(source, analyzePropertyDescription(source, exclusions)); |
||||
} |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private Analysis analyzePropertyDescription(File source, List<String> exclusions) { |
||||
Map<String, Object> json = readJsonContent(source); |
||||
Analysis analysis = new Analysis("The following properties have no description:"); |
||||
List<Map<String, Object>> properties = (List<Map<String, Object>>) json.get("properties"); |
||||
for (Map<String, Object> property : properties) { |
||||
String name = (String) property.get("name"); |
||||
if (!isDeprecated(property) && !isDescribed(property) && !isExcluded(exclusions, name)) { |
||||
analysis.addItem(name); |
||||
} |
||||
} |
||||
return analysis; |
||||
} |
||||
|
||||
private boolean isExcluded(List<String> exclusions, String propertyName) { |
||||
for (String exclusion : exclusions) { |
||||
if (propertyName.equals(exclusion)) { |
||||
return true; |
||||
} |
||||
if (exclusion.endsWith(".*")) { |
||||
if (propertyName.startsWith(exclusion.substring(0, exclusion.length() - 2))) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
private boolean isDeprecated(Map<String, Object> property) { |
||||
return property.get("deprecation") != null; |
||||
} |
||||
|
||||
private boolean isDescribed(Map<String, Object> property) { |
||||
return property.get("description") != null; |
||||
} |
||||
|
||||
@SuppressWarnings("unchecked") |
||||
private Map<String, Object> readJsonContent(File source) { |
||||
return this.jsonMapperSupplier.obtain().readValue(source, Map.class); |
||||
} |
||||
|
||||
private static <T> void writeAll(PrintWriter writer, Iterable<T> elements, Consumer<T> itemWriter) { |
||||
Iterator<T> it = elements.iterator(); |
||||
while (it.hasNext()) { |
||||
itemWriter.accept(it.next()); |
||||
if (it.hasNext()) { |
||||
writer.println(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
static class Report { |
||||
|
||||
private final File baseDirectory; |
||||
|
||||
private final MultiValueMap<File, Analysis> analyses = new LinkedMultiValueMap<>(); |
||||
|
||||
Report(File baseDirectory) { |
||||
this.baseDirectory = baseDirectory; |
||||
} |
||||
|
||||
void registerAnalysis(File path, Analysis analysis) { |
||||
this.analyses.add(path, analysis); |
||||
} |
||||
|
||||
boolean hasProblems() { |
||||
return this.analyses.values() |
||||
.stream() |
||||
.anyMatch((candidates) -> candidates.stream().anyMatch(Analysis::hasProblems)); |
||||
} |
||||
|
||||
List<Analysis> getAnalyses(File source) { |
||||
return this.analyses.getOrDefault(source, Collections.emptyList()); |
||||
} |
||||
|
||||
/** |
||||
* Write this report to the given {@code file}. |
||||
* @param file the file to write the report to |
||||
*/ |
||||
void write(File file) throws IOException { |
||||
Files.writeString(file.toPath(), createContent(), StandardOpenOption.CREATE, |
||||
StandardOpenOption.TRUNCATE_EXISTING); |
||||
} |
||||
|
||||
private String createContent() { |
||||
if (this.analyses.isEmpty()) { |
||||
return "No problems found."; |
||||
} |
||||
StringWriter out = new StringWriter(); |
||||
try (PrintWriter writer = new PrintWriter(out)) { |
||||
writeAll(writer, this.analyses.entrySet(), (entry) -> { |
||||
writer.println(this.baseDirectory.toPath().relativize(entry.getKey().toPath())); |
||||
boolean hasProblems = entry.getValue().stream().anyMatch(Analysis::hasProblems); |
||||
if (hasProblems) { |
||||
writeAll(writer, entry.getValue(), (analysis) -> analysis.createDetails(writer)); |
||||
} |
||||
else { |
||||
writer.println("No problems found."); |
||||
} |
||||
}); |
||||
} |
||||
return out.toString(); |
||||
} |
||||
|
||||
} |
||||
|
||||
static class Analysis { |
||||
|
||||
private final String header; |
||||
|
||||
private final List<String> items; |
||||
|
||||
Analysis(String header) { |
||||
this.header = header; |
||||
this.items = new ArrayList<>(); |
||||
} |
||||
|
||||
void addItem(String item) { |
||||
this.items.add(item); |
||||
} |
||||
|
||||
boolean hasProblems() { |
||||
return !this.items.isEmpty(); |
||||
} |
||||
|
||||
List<String> getItems() { |
||||
return this.items; |
||||
} |
||||
|
||||
void createDetails(PrintWriter writer) { |
||||
writer.println(this.header); |
||||
if (this.items.isEmpty()) { |
||||
writer.println("No problems found."); |
||||
} |
||||
else { |
||||
for (String item : this.items) { |
||||
writer.println("\t- " + item); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
StringWriter out = new StringWriter(); |
||||
PrintWriter writer = new PrintWriter(out); |
||||
createDetails(writer); |
||||
return out.toString(); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,185 @@
@@ -0,0 +1,185 @@
|
||||
/* |
||||
* Copyright 2012-present 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.build.context.properties; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.nio.file.Files; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.io.TempDir; |
||||
|
||||
import org.springframework.boot.build.context.properties.ConfigurationPropertiesAnalyzer.Analysis; |
||||
import org.springframework.boot.build.context.properties.ConfigurationPropertiesAnalyzer.Report; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; |
||||
|
||||
/** |
||||
* Tests for {@link ConfigurationPropertiesAnalyzer}. |
||||
* |
||||
* @author Stephane Nicoll |
||||
*/ |
||||
class ConfigurationPropertiesAnalyzerTests { |
||||
|
||||
@Test |
||||
void createAnalyzerWithNoSource() { |
||||
assertThatIllegalArgumentException() |
||||
.isThrownBy(() -> new ConfigurationPropertiesAnalyzer(Collections.emptyList())) |
||||
.withMessage("At least one source should be provided"); |
||||
} |
||||
|
||||
@Test |
||||
void analyzeSortWithAlphabeticalOrder(@TempDir File tempDir) throws IOException { |
||||
File metadata = new File(tempDir, "metadata.json"); |
||||
Files.writeString(metadata.toPath(), """ |
||||
{ "properties": [ |
||||
{ "name": "abc"}, {"name": "def"}, {"name": "xyz"} |
||||
] |
||||
}"""); |
||||
Report report = new Report(tempDir); |
||||
ConfigurationPropertiesAnalyzer analyzer = new ConfigurationPropertiesAnalyzer(List.of(metadata)); |
||||
analyzer.analyzeSort(report); |
||||
assertThat(report.hasProblems()).isFalse(); |
||||
assertThat(report.getAnalyses(metadata)).singleElement() |
||||
.satisfies(((analysis) -> assertThat(analysis.getItems()).isEmpty())); |
||||
} |
||||
|
||||
@Test |
||||
void analyzeSortWithViolations(@TempDir File tempDir) throws IOException { |
||||
File metadata = new File(tempDir, "metadata.json"); |
||||
Files.writeString(metadata.toPath(), """ |
||||
{ "properties": [ |
||||
{ "name": "def"}, {"name": "abc"}, {"name": "xyz"} |
||||
] |
||||
}"""); |
||||
Report report = new Report(tempDir); |
||||
ConfigurationPropertiesAnalyzer analyzer = new ConfigurationPropertiesAnalyzer(List.of(metadata)); |
||||
analyzer.analyzeSort(report); |
||||
assertThat(report.hasProblems()).isTrue(); |
||||
assertThat(report.getAnalyses(metadata)).singleElement() |
||||
.satisfies((analysis) -> assertThat(analysis.getItems()).containsExactly( |
||||
"Wrong order at $.properties[0].name - expected 'abc' but found 'def'", |
||||
"Wrong order at $.properties[1].name - expected 'def' but found 'abc'")); |
||||
} |
||||
|
||||
@Test |
||||
void analyzePropertyDescription(@TempDir File tempDir) throws IOException { |
||||
File metadata = new File(tempDir, "metadata.json"); |
||||
Files.writeString(metadata.toPath(), """ |
||||
{ "properties": [ |
||||
{ "name": "abc", "description": "This is abc." }, |
||||
{ "name": "def", "description": "This is def." }, |
||||
{ "name": "xyz", "description": "This is xyz." } |
||||
] |
||||
}"""); |
||||
Report report = new Report(tempDir); |
||||
ConfigurationPropertiesAnalyzer analyzer = new ConfigurationPropertiesAnalyzer(List.of(metadata)); |
||||
analyzer.analyzePropertyDescription(report, List.of()); |
||||
assertThat(report.hasProblems()).isFalse(); |
||||
assertThat(report.getAnalyses(metadata)).singleElement() |
||||
.satisfies(((analysis) -> assertThat(analysis.getItems()).isEmpty())); |
||||
} |
||||
|
||||
@Test |
||||
void analyzePropertyDescriptionWithMissingDescription(@TempDir File tempDir) throws IOException { |
||||
File metadata = new File(tempDir, "metadata.json"); |
||||
Files.writeString(metadata.toPath(), """ |
||||
{ "properties": [ |
||||
{ "name": "abc", "description": "This is abc." }, |
||||
{ "name": "def" }, |
||||
{ "name": "xyz", "description": "This is xyz." } |
||||
] |
||||
}"""); |
||||
Report report = new Report(tempDir); |
||||
ConfigurationPropertiesAnalyzer analyzer = new ConfigurationPropertiesAnalyzer(List.of(metadata)); |
||||
analyzer.analyzePropertyDescription(report, List.of()); |
||||
assertThat(report.hasProblems()).isTrue(); |
||||
assertThat(report.getAnalyses(metadata)).singleElement() |
||||
.satisfies(((analysis) -> assertThat(analysis.getItems()).containsExactly("def"))); |
||||
} |
||||
|
||||
@Test |
||||
void writeEmptyReport(@TempDir File tempDir) throws IOException { |
||||
assertThat(writeToFile(tempDir, new Report(tempDir))).hasContent("No problems found."); |
||||
} |
||||
|
||||
@Test |
||||
void writeReportWithNoProblemsFound(@TempDir File tempDir) throws IOException { |
||||
Report report = new Report(tempDir); |
||||
File first = new File(tempDir, "metadata-1.json"); |
||||
report.registerAnalysis(first, new Analysis("Check for things:")); |
||||
File second = new File(tempDir, "metadata-2.json"); |
||||
report.registerAnalysis(second, new Analysis("Check for other things:")); |
||||
assertThat(writeToFile(tempDir, report)).content().isEqualTo(""" |
||||
metadata-1.json |
||||
No problems found. |
||||
|
||||
metadata-2.json |
||||
No problems found. |
||||
"""); |
||||
} |
||||
|
||||
@Test |
||||
void writeReportWithOneProblem(@TempDir File tempDir) throws IOException { |
||||
Report report = new Report(tempDir); |
||||
File metadata = new File(tempDir, "metadata-1.json"); |
||||
Analysis analysis = new Analysis("Check for things:"); |
||||
analysis.addItem("Should not be deprecated"); |
||||
report.registerAnalysis(metadata, analysis); |
||||
report.registerAnalysis(metadata, new Analysis("Check for other things:")); |
||||
assertThat(writeToFile(tempDir, report)).content().isEqualTo(""" |
||||
metadata-1.json |
||||
Check for things: |
||||
- Should not be deprecated |
||||
|
||||
Check for other things: |
||||
No problems found. |
||||
"""); |
||||
} |
||||
|
||||
@Test |
||||
void writeReportWithSeveralProblems(@TempDir File tempDir) throws IOException { |
||||
Report report = new Report(tempDir); |
||||
File metadata = new File(tempDir, "metadata-1.json"); |
||||
Analysis firstAnalysis = new Analysis("Check for things:"); |
||||
firstAnalysis.addItem("Should not be deprecated"); |
||||
firstAnalysis.addItem("Should not be public"); |
||||
report.registerAnalysis(metadata, firstAnalysis); |
||||
Analysis secondAnalysis = new Analysis("Check for other things:"); |
||||
secondAnalysis.addItem("Field 'this' not expected"); |
||||
report.registerAnalysis(metadata, secondAnalysis); |
||||
assertThat(writeToFile(tempDir, report)).content().isEqualTo(""" |
||||
metadata-1.json |
||||
Check for things: |
||||
- Should not be deprecated |
||||
- Should not be public |
||||
|
||||
Check for other things: |
||||
- Field 'this' not expected |
||||
"""); |
||||
} |
||||
|
||||
private File writeToFile(File directory, Report report) throws IOException { |
||||
File file = new File(directory, "report.txt"); |
||||
report.write(file); |
||||
return file; |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue