package org.checkerframework.framework.test; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; import org.checkerframework.framework.test.diagnostics.TestDiagnostic; import org.checkerframework.framework.test.diagnostics.TestDiagnosticUtils; import org.checkerframework.framework.util.PluginUtil; /** * Represents the test results from typechecking one or more java files using the given * TestConfiguration. */ public class TypecheckResult { private final TestConfiguration configuration; private final CompilationResult compilationResult; private final List<TestDiagnostic> expectedDiagnostics; private final boolean testFailed; private final List<TestDiagnostic> missingDiagnostics; private final List<TestDiagnostic> unexpectedDiagnostics; protected TypecheckResult( TestConfiguration configuration, CompilationResult compilationResult, List<TestDiagnostic> expectedDiagnostics, boolean testFailed, List<TestDiagnostic> missingDiagnostics, List<TestDiagnostic> unexpectedDiagnostics) { this.configuration = configuration; this.compilationResult = compilationResult; this.expectedDiagnostics = expectedDiagnostics; this.testFailed = testFailed; this.missingDiagnostics = missingDiagnostics; this.unexpectedDiagnostics = unexpectedDiagnostics; } public TestConfiguration getConfiguration() { return configuration; } public CompilationResult getCompilationResult() { return compilationResult; } public List<Diagnostic<? extends JavaFileObject>> getActualDiagnostics() { return compilationResult.getDiagnostics(); } public List<TestDiagnostic> getExpectedDiagnostics() { return expectedDiagnostics; } public boolean didTestFail() { return testFailed; } public List<TestDiagnostic> getMissingDiagnostics() { return missingDiagnostics; } public List<TestDiagnostic> getUnexpectedDiagnostics() { return unexpectedDiagnostics; } public List<String> getErrorHeaders() { List<String> errorHeaders = new ArrayList<>(); // none of these should be true if the test didn't fail if (testFailed) { if (compilationResult.compiledWithoutError() && !expectedDiagnostics.isEmpty()) { errorHeaders.add( "The test run was expected to issue errors/warnings, but it did not."); } else if (!compilationResult.compiledWithoutError() && expectedDiagnostics.isEmpty()) { errorHeaders.add( "The test run was not expected to issue errors/warnings, but it did."); } if (!unexpectedDiagnostics.isEmpty() || !missingDiagnostics.isEmpty()) { int numExpected = expectedDiagnostics.size(); int numFound = numExpected - missingDiagnostics.size(); errorHeaders.add( numFound + " out of " + numExpected + " expected diagnostics " + (numFound == 1 ? "was" : "were") + " found."); } } return errorHeaders; } public String summarize() { if (testFailed) { StringBuilder summaryBuilder = new StringBuilder(); summaryBuilder.append(PluginUtil.join("\n", getErrorHeaders())); summaryBuilder.append("\n"); if (!missingDiagnostics.isEmpty()) { summaryBuilder.append( missingDiagnostics.size() == 1 ? "1 expected diagnostic was not found:\n" : missingDiagnostics.size() + " expected diagnostics were not found:\n"); for (TestDiagnostic missing : missingDiagnostics) { summaryBuilder.append(missing); summaryBuilder.append("\n"); } } if (!unexpectedDiagnostics.isEmpty()) { summaryBuilder.append( unexpectedDiagnostics.size() == 1 ? "1 unexpected diagnostic was found:\n" : unexpectedDiagnostics.size() + " unexpected diagnostics were found:\n"); for (TestDiagnostic unexpected : unexpectedDiagnostics) { summaryBuilder.append(unexpected); summaryBuilder.append("\n"); } } summaryBuilder.append( "While type-checking " + TestUtilities.summarizeSourceFiles( configuration.getTestSourceFiles())); return summaryBuilder.toString(); } return ""; } public static TypecheckResult fromCompilationResults( TestConfiguration configuration, CompilationResult result, List<TestDiagnostic> expectedDiagnostics) { boolean usingAnomsgtxt = configuration.getOptions().containsKey("-Anomsgtext"); final Set<TestDiagnostic> actualDiagnostics = TestDiagnosticUtils.fromJavaxDiagnosticList( result.getDiagnostics(), usingAnomsgtxt); final Set<TestDiagnostic> unexpectedDiagnostics = new LinkedHashSet<>(); unexpectedDiagnostics.addAll(actualDiagnostics); unexpectedDiagnostics.removeAll(expectedDiagnostics); final List<TestDiagnostic> missingDiagnostics = new LinkedList<>(expectedDiagnostics); missingDiagnostics.removeAll(actualDiagnostics); boolean testFailed = !unexpectedDiagnostics.isEmpty() || !missingDiagnostics.isEmpty(); return new TypecheckResult( configuration, result, expectedDiagnostics, testFailed, missingDiagnostics, new ArrayList<>(unexpectedDiagnostics)); } public static TypecheckResult fromCompilationResultsExpectedDiagnostics( TestConfiguration configuration, CompilationResult result, List<TestDiagnostic> expectedDiagnostics) { boolean usingAnomsgtxt = configuration.getOptions().containsKey("-Anomsgtext"); final Set<TestDiagnostic> actualDiagnostics = TestDiagnosticUtils.fromJavaxDiagnosticList( result.getDiagnostics(), usingAnomsgtxt); final Set<TestDiagnostic> unexpectedDiagnostics = new LinkedHashSet<>(); unexpectedDiagnostics.addAll(actualDiagnostics); unexpectedDiagnostics.removeAll(expectedDiagnostics); final List<TestDiagnostic> missingDiagnostics = new LinkedList<>(expectedDiagnostics); missingDiagnostics.removeAll(actualDiagnostics); boolean testFailed = !unexpectedDiagnostics.isEmpty() || !missingDiagnostics.isEmpty(); return new TypecheckResult( configuration, result, expectedDiagnostics, testFailed, missingDiagnostics, new ArrayList<>(unexpectedDiagnostics)); } }