diff --git a/.travis.yml b/.travis.yml index 8ce15e93c..f9e1963f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,24 @@ language: java -jdk: - - oraclejdk8 install: true script: mvn clean install -DprocessorIntegrationTest.toolchainsFile=etc/toolchains-travis-jenkins.xml -B -V after_success: - mvn jacoco:report && bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports" +matrix: + include: + - jdk: oraclejdk8 + - jdk: openjdk11 + # Only run the processor and its dependencies + # The integration tests are using the maven toolchain and that is not yet ready for Java 11 + # There is an issue with the documentation so skip it + script: mvn -B -V clean install -pl processor -am + # Only run the processor and its dependencies + # The integration tests are using the maven toolchain and that is not yet ready for Java EA + # There is an issue with the documentation so skip it + - jdk: openjdk-ea + script: mvn -B -V clean install -pl processor -am + allow_failures: + - jdk: openjdk-ea deploy: provider: script script: "test ${TRAVIS_TEST_RESULT} -eq 0 && mvn -s etc/travis-settings.xml -DskipTests=true deploy" diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/date/DateConversionTest.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/date/DateConversionTest.java index ee643032b..680303b33 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/date/DateConversionTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/date/DateConversionTest.java @@ -22,6 +22,9 @@ import org.junit.runner.RunWith; import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; +import org.mapstruct.ap.testutil.runner.Compiler; +import org.mapstruct.ap.testutil.runner.DisabledOnCompiler; +import org.mapstruct.ap.testutil.runner.EnabledOnCompiler; /** * Tests application of format strings for conversions between strings and dates. @@ -43,6 +46,8 @@ public class DateConversionTest { } @Test + @DisabledOnCompiler(Compiler.JDK11) + // See https://bugs.openjdk.java.net/browse/JDK-8211262, there is a difference in the default formats on Java 9+ public void shouldApplyDateFormatForConversions() { Source source = new Source(); source.setDate( new GregorianCalendar( 2013, 6, 6 ).getTime() ); @@ -56,6 +61,23 @@ public class DateConversionTest { } @Test + @EnabledOnCompiler(Compiler.JDK11) + // See https://bugs.openjdk.java.net/browse/JDK-8211262, there is a difference in the default formats on Java 9+ + public void shouldApplyDateFormatForConversionsJdk11() { + Source source = new Source(); + source.setDate( new GregorianCalendar( 2013, 6, 6 ).getTime() ); + source.setAnotherDate( new GregorianCalendar( 2013, 1, 14 ).getTime() ); + + Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source ); + + assertThat( target ).isNotNull(); + assertThat( target.getDate() ).isEqualTo( "06.07.2013" ); + assertThat( target.getAnotherDate() ).isEqualTo( "14.02.13, 00:00" ); + } + + @Test + @DisabledOnCompiler(Compiler.JDK11) + // See https://bugs.openjdk.java.net/browse/JDK-8211262, there is a difference in the default formats on Java 9+ public void shouldApplyDateFormatForConversionInReverseMapping() { Target target = new Target(); target.setDate( "06.07.2013" ); @@ -68,6 +90,21 @@ public class DateConversionTest { assertThat( source.getAnotherDate() ).isEqualTo( new GregorianCalendar( 2013, 1, 14, 8, 30 ).getTime() ); } + @Test + @EnabledOnCompiler(Compiler.JDK11) + // See https://bugs.openjdk.java.net/browse/JDK-8211262, there is a difference in the default formats on Java 9+ + public void shouldApplyDateFormatForConversionInReverseMappingJdk11() { + Target target = new Target(); + target.setDate( "06.07.2013" ); + target.setAnotherDate( "14.02.13, 8:30" ); + + Source source = SourceTargetMapper.INSTANCE.targetToSource( target ); + + assertThat( source ).isNotNull(); + assertThat( source.getDate() ).isEqualTo( new GregorianCalendar( 2013, 6, 6 ).getTime() ); + assertThat( source.getAnotherDate() ).isEqualTo( new GregorianCalendar( 2013, 1, 14, 8, 30 ).getTime() ); + } + @Test public void shouldApplyStringConversionForIterableMethod() { List dates = Arrays.asList( diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java index 60dca06ce..30c96395b 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java @@ -22,6 +22,9 @@ import org.junit.runner.RunWith; import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; +import org.mapstruct.ap.testutil.runner.Compiler; +import org.mapstruct.ap.testutil.runner.DisabledOnCompiler; +import org.mapstruct.ap.testutil.runner.EnabledOnCompiler; /** * Tests the conversion between Joda-Time types and String/Date/Calendar. @@ -75,6 +78,8 @@ public class JodaConversionTest { } @Test + @DisabledOnCompiler(Compiler.JDK11) + // See https://bugs.openjdk.java.net/browse/JDK-8211262, there is a difference in the default formats on Java 9+ public void testSourceToTargetMappingForStrings() { Source src = new Source(); src.setLocalTime( new LocalTime( 0, 0 ) ); @@ -100,6 +105,34 @@ public class JodaConversionTest { assertThat( target.getLocalTime() ).isEqualTo( "00:00:00" ); } + @Test + @EnabledOnCompiler(Compiler.JDK11) + // See https://bugs.openjdk.java.net/browse/JDK-8211262, there is a difference in the default formats on Java 9+ + public void testSourceToTargetMappingForStringsJdk11() { + Source src = new Source(); + src.setLocalTime( new LocalTime( 0, 0 ) ); + src.setLocalDate( new LocalDate( 2014, 1, 1 ) ); + src.setLocalDateTime( new LocalDateTime( 2014, 1, 1, 0, 0 ) ); + src.setDateTime( new DateTime( 2014, 1, 1, 0, 0, 0, DateTimeZone.UTC ) ); + + // with given format + Target target = SourceTargetMapper.INSTANCE.sourceToTarget( src ); + + assertThat( target ).isNotNull(); + assertThat( target.getDateTime() ).isEqualTo( "01.01.2014 00:00 UTC" ); + assertThat( target.getLocalDateTime() ).isEqualTo( "01.01.2014 00:00" ); + assertThat( target.getLocalDate() ).isEqualTo( "01.01.2014" ); + assertThat( target.getLocalTime() ).isEqualTo( "00:00" ); + + // and now with default mappings + target = SourceTargetMapper.INSTANCE.sourceToTargetDefaultMapping( src ); + assertThat( target ).isNotNull(); + assertThat( target.getDateTime() ).isEqualTo( "1. Januar 2014 um 00:00:00 UTC" ); + assertThat( target.getLocalDateTime() ).isEqualTo( "1. Januar 2014 um 00:00:00" ); + assertThat( target.getLocalDate() ).isEqualTo( "1. Januar 2014" ); + assertThat( target.getLocalTime() ).isEqualTo( "00:00:00" ); + } + @Test public void testStringToDateTime() { String dateTimeAsString = "01.01.2014 00:00 UTC"; diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java b/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java index 9b374273f..62325ac8f 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/assertions/JavaFileAssert.java @@ -38,6 +38,8 @@ public class JavaFileAssert extends FileAssert { "\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+\\d{4}\","; private static final String GENERATED_COMMENTS_REGEX = "\\s+comments = \"version: , compiler: .*, environment: " + ".*\""; + private static final String IMPORT_GENERATED_ANNOTATION_REGEX = "import javax\\.annotation\\.(processing\\.)?" + + "Generated;"; private Diff diff = new Diff(); @@ -135,7 +137,8 @@ public class JavaFileAssert extends FileAssert { else if ( delta.getType() == Delta.TYPE.CHANGE ) { List lines = delta.getOriginal().getLines(); if ( lines.size() == 1 ) { - return lines.get( 0 ).matches( GENERATED_DATE_REGEX ); + return lines.get( 0 ).matches( GENERATED_DATE_REGEX ) || + lines.get( 0 ).matches( IMPORT_GENERATED_ANNOTATION_REGEX ); } else if ( lines.size() == 2 ) { return lines.get( 0 ).matches( GENERATED_DATE_REGEX ) && diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/AnnotationProcessorTestRunner.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/AnnotationProcessorTestRunner.java index 02f986d54..2688f9f7d 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/runner/AnnotationProcessorTestRunner.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/AnnotationProcessorTestRunner.java @@ -37,6 +37,19 @@ import org.mapstruct.ap.testutil.compilation.annotation.ProcessorOption; * @author Andreas Gudian */ public class AnnotationProcessorTestRunner extends ParentRunner { + + private static final boolean IS_AT_LEAST_JAVA_9 = isIsAtLeastJava9(); + + private static boolean isIsAtLeastJava9() { + try { + Runtime.class.getMethod( "version" ); + return true; + } + catch ( NoSuchMethodException e ) { + return false; + } + } + private final List runners; /** @@ -57,6 +70,12 @@ public class AnnotationProcessorTestRunner extends ParentRunner { if (singleCompiler != null) { return Arrays. asList( new InnerAnnotationProcessorRunner( klass, singleCompiler.value() ) ); } + else if ( IS_AT_LEAST_JAVA_9 ) { + // Current tycho-compiler-jdt (0.26.0) is not compatible with Java 11 + // Updating to latest version 1.3.0 fails some tests + // Once https://github.com/mapstruct/mapstruct/pull/1587 is resolved we can remove this line + return Arrays.asList( new InnerAnnotationProcessorRunner( klass, Compiler.JDK11 ) ); + } return Arrays. asList( new InnerAnnotationProcessorRunner( klass, Compiler.JDK ), diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/Compiler.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/Compiler.java index 4e11318be..d59a7ed0d 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/runner/Compiler.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/Compiler.java @@ -10,5 +10,5 @@ package org.mapstruct.ap.testutil.runner; * */ public enum Compiler { - JDK, ECLIPSE; + JDK, JDK11, ECLIPSE; } diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java index 73693e4cb..f6ddcbd2b 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/CompilingStatement.java @@ -128,6 +128,7 @@ abstract class CompilingStatement extends Statement { "javax.inject", "spring-beans", "spring-context", + "jaxb-api", "joda-time" }; return filterBootClassPath( whitelist ); diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/DisabledOnCompiler.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/DisabledOnCompiler.java new file mode 100644 index 000000000..41bcdb100 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/DisabledOnCompiler.java @@ -0,0 +1,26 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.testutil.runner; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This should be used with care. + * This is similar to the JUnit 5 DisabledOnJre (once we have JUnit 5 we can replace this one) + * + * @author Filip Hrisafov + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface DisabledOnCompiler { + /** + * @return The compiler to use. + */ + Compiler value(); +} diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/EnabledOnCompiler.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/EnabledOnCompiler.java new file mode 100644 index 000000000..e297bd2c6 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/EnabledOnCompiler.java @@ -0,0 +1,26 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.testutil.runner; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This should be used with care. + * This is similar to the JUnit 5 EnabledOnJre (once we have JUnit 5 we can replace this one) + * + * @author Filip Hrisafov + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface EnabledOnCompiler { + /** + * @return The compiler to use. + */ + Compiler value(); +} diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/InnerAnnotationProcessorRunner.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/InnerAnnotationProcessorRunner.java index 9b9dc868b..4850a4870 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/runner/InnerAnnotationProcessorRunner.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/InnerAnnotationProcessorRunner.java @@ -60,6 +60,25 @@ class InnerAnnotationProcessorRunner extends BlockJUnit4ClassRunner { Thread.currentThread().setContextClassLoader( testClassLoader ); } + @Override + protected boolean isIgnored(FrameworkMethod child) { + return super.isIgnored( child ) || isIgnoredForCompiler( child ); + } + + protected boolean isIgnoredForCompiler(FrameworkMethod child) { + EnabledOnCompiler enabledOnCompiler = child.getAnnotation( EnabledOnCompiler.class ); + if ( enabledOnCompiler != null ) { + return enabledOnCompiler.value() != compiler; + } + + DisabledOnCompiler disabledOnCompiler = child.getAnnotation( DisabledOnCompiler.class ); + if ( disabledOnCompiler != null ) { + return disabledOnCompiler.value() == compiler; + } + + return false; + } + @Override protected TestClass createTestClass(final Class testClass) { replacableTestClass = new ReplacableTestClass( testClass ); @@ -98,6 +117,9 @@ class InnerAnnotationProcessorRunner extends BlockJUnit4ClassRunner { if ( compiler == Compiler.JDK ) { return new JdkCompilingStatement( method, compilationCache ); } + else if ( compiler == Compiler.JDK11 ) { + return new Jdk11CompilingStatement( method, compilationCache ); + } else { return new EclipseCompilingStatement( method, compilationCache ); } diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/runner/Jdk11CompilingStatement.java b/processor/src/test/java/org/mapstruct/ap/testutil/runner/Jdk11CompilingStatement.java new file mode 100644 index 000000000..30f12aead --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/testutil/runner/Jdk11CompilingStatement.java @@ -0,0 +1,37 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.testutil.runner; + +import java.util.List; + +import org.junit.runners.model.FrameworkMethod; +import org.mapstruct.ap.testutil.compilation.model.DiagnosticDescriptor; + +/** + * Statement that uses the JDK compiler to compile. + * + * @author Filip Hrisafov + */ +class Jdk11CompilingStatement extends JdkCompilingStatement { + + Jdk11CompilingStatement(FrameworkMethod method, CompilationCache compilationCache) { + super( method, compilationCache ); + } + + + /** + * The JDK 11 compiler reports all ERROR diagnostics properly. Also when there are multiple per line. + */ + @Override + protected List filterExpectedDiagnostics(List expectedDiagnostics) { + return expectedDiagnostics; + } + + @Override + protected String getPathSuffix() { + return "_jdk"; + } +}