#36 Allowing messages to be used in diagnostic expectations

This commit is contained in:
Gunnar Morling 2013-06-09 21:16:24 +02:00
parent e53adbd817
commit 60126183a3
6 changed files with 125 additions and 16 deletions

View File

@ -364,11 +364,11 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
if ( declaringMapper == null ) { if ( declaringMapper == null ) {
if ( parameter.getType().isIterableType() && !returnType.isIterableType() ) { if ( parameter.getType().isIterableType() && !returnType.isIterableType() ) {
reportError( "Can't generate mapping method from iterable type to non-iterable ype.", method ); reportError( "Can't generate mapping method from iterable type to non-iterable type.", method );
mappingErroneous = true; mappingErroneous = true;
} }
if ( !parameter.getType().isIterableType() && returnType.isIterableType() ) { if ( !parameter.getType().isIterableType() && returnType.isIterableType() ) {
reportError( "Can't generate mapping method from non-iterable type to iterable ype.", method ); reportError( "Can't generate mapping method from non-iterable type to iterable type.", method );
mappingErroneous = true; mappingErroneous = true;
} }
if ( parameter.getType().isPrimitive() ) { if ( parameter.getType().isPrimitive() ) {

View File

@ -26,6 +26,8 @@ import java.net.URLClassLoader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List; import java.util.List;
import javax.tools.DiagnosticCollector; import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler; import javax.tools.JavaCompiler;
@ -39,19 +41,26 @@ import org.mapstruct.ap.MappingProcessor;
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult; import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
import org.mapstruct.ap.testutil.compilation.model.CompilationOutcomeDescriptor; import org.mapstruct.ap.testutil.compilation.model.CompilationOutcomeDescriptor;
import org.mapstruct.ap.testutil.compilation.model.DiagnosticDescriptor;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeMethod;
import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Assertions.assertThat;
/** /**
* Base class for all mapper tests. The classes to be compiled for a given test * Base class for all mapper tests.
* method must be specified via {@link WithClasses}. * </p>
* The classes to be compiled for a given test method must be specified via
* {@link WithClasses}. Optionally the expected compilation outcome and expected
* diagnostics can be specified via {@link ExpectedCompilationOutcome}. If no
* outcome is specified, a successful compilation is assumed.
* *
* @author Gunnar Morling * @author Gunnar Morling
*/ */
public abstract class MapperTestBase { public abstract class MapperTestBase {
private static final DiagnosticDescriptorComparator COMPARATOR = new DiagnosticDescriptorComparator();
private JavaCompiler compiler; private JavaCompiler compiler;
private String sourceDir; private String sourceDir;
private String classOutputDir; private String classOutputDir;
@ -118,7 +127,50 @@ public abstract class MapperTestBase {
.isEqualTo( CompilationResult.FAILED ); .isEqualTo( CompilationResult.FAILED );
} }
assertThat( actualResult.getDiagnostics() ).isEqualTo( expectedResult.getDiagnostics() ); assertDiagnostics( actualResult.getDiagnostics(), expectedResult.getDiagnostics() );
}
private void assertDiagnostics(List<DiagnosticDescriptor> actualDiagnostics,
List<DiagnosticDescriptor> expectedDiagnostics) {
Collections.sort( actualDiagnostics, COMPARATOR );
Collections.sort( expectedDiagnostics, COMPARATOR );
Iterator<DiagnosticDescriptor> actualIterator = actualDiagnostics.iterator();
Iterator<DiagnosticDescriptor> expectedIterator = expectedDiagnostics.iterator();
while ( actualIterator.hasNext() ) {
assertThat( expectedIterator.hasNext() ).describedAs(
String.format(
"Found less diagnostics than expected. Actual: %s; Expected: %s.",
actualDiagnostics,
expectedDiagnostics
)
).isTrue();
DiagnosticDescriptor actual = actualIterator.next();
DiagnosticDescriptor expected = expectedIterator.next();
assertThat( actual.getSourceFileName() ).isEqualTo( expected.getSourceFileName() );
assertThat( actual.getLine() ).isEqualTo( expected.getLine() );
assertThat( actual.getKind() ).isEqualTo( expected.getKind() );
assertThat( actual.getMessage() ).describedAs(
String.format(
"%s:%s %s",
actual.getSourceFileName(),
actual.getLine(),
actual.getKind()
)
).matches( expected.getMessage() );
}
assertThat( expectedIterator.hasNext() ).describedAs(
String.format(
"Found more diagnostics than expected. Actual: %s; Expected: %s.",
actualDiagnostics,
expectedDiagnostics
)
).isFalse();
} }
/** /**
@ -221,4 +273,24 @@ public abstract class MapperTestBase {
} }
path.delete(); path.delete();
} }
private static class DiagnosticDescriptorComparator implements Comparator<DiagnosticDescriptor> {
@Override
public int compare(DiagnosticDescriptor o1, DiagnosticDescriptor o2) {
int result = o1.getSourceFileName().compareTo( o2.getSourceFileName() );
if ( result != 0 ) {
return result;
}
result = Long.valueOf( o1.getLine() ).compareTo( o2.getLine() );
if ( result != 0 ) {
return result;
}
// Using the message is not perfect when using regular expressions,
// but it's better than nothing
return o1.getMessage().compareTo( o2.getMessage() );
}
}
} }

View File

@ -27,9 +27,31 @@ import javax.tools.Diagnostic.Kind;
*/ */
public @interface Diagnostic { public @interface Diagnostic {
/**
* The type for which the diagnostic was created.
*
* @return The type for which the diagnostic was created.
*/
Class<?> type(); Class<?> type();
/**
* The expected kind of diagnostic.
*
* @return The expected kind of diagnostic.
*/
Kind kind(); Kind kind();
/**
* The expected line number of the diagnostic.
*
* @return The expected line number of the diagnostic.
*/
int line(); int line();
/**
* A regular expression matching the expected message of the diagnostic.
*
* @return A regular expression matching the expected message of the diagnostic.
*/
String messageRegExp() default ".*";
} }

View File

@ -29,7 +29,18 @@ import java.lang.annotation.RetentionPolicy;
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface ExpectedCompilationOutcome { public @interface ExpectedCompilationOutcome {
/**
* The expected result of a compilation.
*
* @return The expected result of a compilation.
*/
CompilationResult value(); CompilationResult value();
Diagnostic[] diagnostics(); /**
* The expected diagnostics created during a compilation.
*
* @return The expected diagnostics created during a compilation.
*/
Diagnostic[] diagnostics() default { };
} }

View File

@ -18,10 +18,9 @@
*/ */
package org.mapstruct.ap.testutil.compilation.model; package org.mapstruct.ap.testutil.compilation.model;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import javax.tools.Diagnostic; import javax.tools.Diagnostic;
import javax.tools.Diagnostic.Kind; import javax.tools.Diagnostic.Kind;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
@ -37,10 +36,10 @@ import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutco
public class CompilationOutcomeDescriptor { public class CompilationOutcomeDescriptor {
private CompilationResult compilationResult; private CompilationResult compilationResult;
private Set<DiagnosticDescriptor> diagnostics; private List<DiagnosticDescriptor> diagnostics;
private CompilationOutcomeDescriptor(CompilationResult compilationResult, private CompilationOutcomeDescriptor(CompilationResult compilationResult,
Set<DiagnosticDescriptor> diagnostics) { List<DiagnosticDescriptor> diagnostics) {
this.compilationResult = compilationResult; this.compilationResult = compilationResult;
this.diagnostics = diagnostics; this.diagnostics = diagnostics;
} }
@ -50,11 +49,11 @@ public class CompilationOutcomeDescriptor {
if ( expectedCompilationResult == null ) { if ( expectedCompilationResult == null ) {
return new CompilationOutcomeDescriptor( return new CompilationOutcomeDescriptor(
CompilationResult.SUCCEEDED, CompilationResult.SUCCEEDED,
Collections.<DiagnosticDescriptor>emptySet() Collections.<DiagnosticDescriptor>emptyList()
); );
} }
else { else {
Set<DiagnosticDescriptor> diagnosticDescriptors = new HashSet<DiagnosticDescriptor>(); List<DiagnosticDescriptor> diagnosticDescriptors = new ArrayList<DiagnosticDescriptor>();
for ( org.mapstruct.ap.testutil.compilation.annotation.Diagnostic diagnostic : for ( org.mapstruct.ap.testutil.compilation.annotation.Diagnostic diagnostic :
expectedCompilationResult.diagnostics() ) { expectedCompilationResult.diagnostics() ) {
diagnosticDescriptors.add( DiagnosticDescriptor.forDiagnostic( diagnostic ) ); diagnosticDescriptors.add( DiagnosticDescriptor.forDiagnostic( diagnostic ) );
@ -69,7 +68,7 @@ public class CompilationOutcomeDescriptor {
CompilationResult compilationResult = CompilationResult compilationResult =
compilationSuccessful ? CompilationResult.SUCCEEDED : CompilationResult.FAILED; compilationSuccessful ? CompilationResult.SUCCEEDED : CompilationResult.FAILED;
Set<DiagnosticDescriptor> diagnosticDescriptors = new HashSet<DiagnosticDescriptor>(); List<DiagnosticDescriptor> diagnosticDescriptors = new ArrayList<DiagnosticDescriptor>();
for ( Diagnostic<? extends JavaFileObject> diagnostic : diagnostics ) { for ( Diagnostic<? extends JavaFileObject> diagnostic : diagnostics ) {
//ignore notes created by the compiler //ignore notes created by the compiler
if ( diagnostic.getKind() != Kind.NOTE ) { if ( diagnostic.getKind() != Kind.NOTE ) {
@ -84,7 +83,7 @@ public class CompilationOutcomeDescriptor {
return compilationResult; return compilationResult;
} }
public Set<DiagnosticDescriptor> getDiagnostics() { public List<DiagnosticDescriptor> getDiagnostics() {
return diagnostics; return diagnostics;
} }

View File

@ -46,7 +46,12 @@ public class DiagnosticDescriptor {
public static DiagnosticDescriptor forDiagnostic(Diagnostic diagnostic) { public static DiagnosticDescriptor forDiagnostic(Diagnostic diagnostic) {
String soureFileName = diagnostic.type().getName().replace( ".", File.separator ) + ".java"; String soureFileName = diagnostic.type().getName().replace( ".", File.separator ) + ".java";
return new DiagnosticDescriptor( soureFileName, diagnostic.kind(), diagnostic.line(), "" ); return new DiagnosticDescriptor(
soureFileName,
diagnostic.kind(),
diagnostic.line(),
diagnostic.messageRegExp()
);
} }
public static DiagnosticDescriptor forDiagnostic(String sourceDir, public static DiagnosticDescriptor forDiagnostic(String sourceDir,
@ -55,7 +60,7 @@ public class DiagnosticDescriptor {
getSourceName( sourceDir, diagnostic ), getSourceName( sourceDir, diagnostic ),
diagnostic.getKind(), diagnostic.getKind(),
diagnostic.getLineNumber(), diagnostic.getLineNumber(),
"" diagnostic.getMessage( null )
); );
} }