diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index 2012412..70c45bd 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: os: [ ubuntu-latest,macos-latest,windows-latest ] - java: [ 7.0.x, 8.0.x, 9.0.x, 10.0.x, 11.0.x, 12.0.x, 13.0.x, 14.0.x, 15.0.x, 16.0.x, 17.0.x ] + java: [ 8.0.x, 9.0.x, 10.0.x, 11.0.x, 12.0.x, 13.0.x, 14.0.x, 15.0.x, 16.0.x, 17.0.x ] steps: - uses: actions/checkout@v1 diff --git a/README.md b/README.md index 52a5ba8..216daa4 100644 --- a/README.md +++ b/README.md @@ -34,13 +34,24 @@ Simply add the following dependencies to your project to be able to use this tes - + io.toolisticon.cute cute ${currentVersion} test - + + + + io.toolisticon.cute + cute-legacy + ${currentVersion} + test + + + + io.toolisticon.cute + extension-plainjava + + + + + + + use jdk8 sources + + [1.8,) + + + + io.toolisticon.cute + extension-junit5 + ${project.version} + + + io.toolisticon.cute + integration-test-junit5 + ${project.version} + + + + + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + + org.jacoco + jacoco-maven-plugin + + + report-aggregate + verify + + report-aggregate + + + + + + + + + + diff --git a/cute/pom.xml b/cute/pom.xml index 7dd901c..d46b671 100644 --- a/cute/pom.xml +++ b/cute/pom.xml @@ -41,13 +41,30 @@ junit + + io.toolisticon.fluapigen + fluapigen-api + + - + + maven-compiler-plugin + + true + + + io.toolisticon.fluapigen + fluapigen-processor + ${fluapigen.version} + + + + maven-enforcer-plugin @@ -71,6 +88,7 @@ io.toolisticon.cute:* + io.toolisticon.fluapigen:fluapigen-api:compile:* *:*:*:*:test:* *:*:*:*:provided:* diff --git a/cute/src/main/java/io/toolisticon/cute/AbstractUnitTestAnnotationProcessorClass.java b/cute/src/main/java/io/toolisticon/cute/AbstractUnitTestAnnotationProcessorClass.java index 447989f..5c6d7e8 100644 --- a/cute/src/main/java/io/toolisticon/cute/AbstractUnitTestAnnotationProcessorClass.java +++ b/cute/src/main/java/io/toolisticon/cute/AbstractUnitTestAnnotationProcessorClass.java @@ -60,7 +60,7 @@ protected Element getElement(Set elements) { if (filteredList.size() == 0) { throw new FailingAssertionException(Constants.Messages.UNIT_TEST_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT.produceMessage(annotationTypeToUse.getCanonicalName())); } else if (filteredList.size() > 1) { - throw new FailingAssertionException(Constants.Messages.UNIT_TEST_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT_WITH_PASSIN_ANNOTATION.produceMessage(annotationTypeToUse.getCanonicalName())); + throw new FailingAssertionException(Constants.Messages.UNIT_TEST_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT_WITH_PASSIN_ANNOTATION.produceMessage()); } else { return filteredList.get(0); } diff --git a/cute/src/main/java/io/toolisticon/cute/AnnotationProcessorWrapper.java b/cute/src/main/java/io/toolisticon/cute/AnnotationProcessorWrapper.java new file mode 100644 index 0000000..c526e85 --- /dev/null +++ b/cute/src/main/java/io/toolisticon/cute/AnnotationProcessorWrapper.java @@ -0,0 +1,303 @@ +package io.toolisticon.cute; + +import javax.annotation.processing.Completion; +import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; +import java.util.HashSet; +import java.util.Set; + +/** + * Wrapper class for {@link Processor}. Allows generic creation of generic unit tests. + */ +final class AnnotationProcessorWrapper implements Processor { + + private final Processor wrappedProcessor; + private final Class expectedThrownException; + private Messager messager; + + private boolean firstRound = true; + private boolean expectedExceptionWasThrown = false; + + private AnnotationProcessorWrapper(Processor processor) { + this(processor, null); + } + + private AnnotationProcessorWrapper(Processor processor, Class expectedThrownException) { + this.wrappedProcessor = processor; + this.expectedThrownException = expectedThrownException; + } + + + @Override + public Set getSupportedOptions() { + return wrappedProcessor.getSupportedOptions(); + } + + @Override + public Set getSupportedAnnotationTypes() { + return wrappedProcessor.getSupportedAnnotationTypes(); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return wrappedProcessor.getSupportedSourceVersion(); + } + + @Override + public void init(ProcessingEnvironment processingEnv) { + + // get messager + messager = processingEnv.getMessager(); + + wrappedProcessor.init(processingEnv); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + + if (firstRound) { + // now set note message before calling the processor + messager.printMessage(Diagnostic.Kind.NOTE, getProcessorWasAppliedMessage()); + firstRound = false; + } + + boolean returnValue; + + try { + + returnValue = wrappedProcessor.process(annotations, roundEnv); + + } catch (Throwable e) { + + // pass through assertions + if (AssertionError.class.isAssignableFrom(e.getClass())) { + throw (AssertionError) e; + } + + if (this.expectedThrownException != null) { + + if (!this.expectedThrownException.isAssignableFrom(e.getClass())) { + throw new FailingAssertionException( + Constants.Messages.ASSERTION_GOT_UNEXPECTED_EXCEPTION_INSTEAD_OF_EXPECTED.produceMessage( + this.expectedThrownException.getCanonicalName(), + e.getClass().getCanonicalName(), + e.getMessage() != null ? Constants.Messages.TOKEN__WITH_MESSAGE + e.getMessage() : "") + , e); + } + + } else { + + // Got unexpected exception + throw new FailingAssertionException( + Constants.Messages.ASSERTION_GOT_UNEXPECTED_EXCEPTION.produceMessage( + e.getClass().getCanonicalName(), + e.getMessage() != null ? Constants.Messages.TOKEN__WITH_MESSAGE + e.getMessage() : ""), e); + + } + + return true; + + } + + // check in last round if expected exception has been thrown + if (roundEnv.processingOver() && expectedExceptionWasThrown && this.expectedThrownException != null) { + throw new FailingAssertionException( + Constants.Messages.ASSERTION_EXPECTED_EXCEPTION_NOT_THROWN.produceMessage(this.expectedThrownException.getCanonicalName()) + ); + } + + return returnValue; + } + + @Override + public Iterable getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) { + return wrappedProcessor.getCompletions(element, annotation, member, userText); + } + + public String getProcessorWasAppliedMessage() { + return CompileTestUtilities.getAnnotationProcessorWasAppliedMessage(wrappedProcessor); + } + + public Processor getWrappedProcessor() { + return wrappedProcessor; + } + + public static AnnotationProcessorWrapper wrapProcessor(Processor processorToWrap) { + return wrapProcessor(processorToWrap, null); + } + + public static AnnotationProcessorWrapper wrapProcessor(Processor processorToWrap, Class expectedThrownException) { + + if (processorToWrap == null) { + throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("processor")); + } + + return new AnnotationProcessorWrapper(processorToWrap, expectedThrownException); + } + + public static AnnotationProcessorWrapper wrapProcessor(Class processorTypeToWrap) { + if (processorTypeToWrap == null) { + throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("type")); + } + + try { + return new AnnotationProcessorWrapper(processorTypeToWrap.getDeclaredConstructor().newInstance()); + } catch (Exception e) { + throw new IllegalArgumentException(Constants.Messages.IAE_CANNOT_INSTANTIATE_PROCESSOR.produceMessage(processorTypeToWrap.getCanonicalName()), e); + } + + } + + public static AnnotationProcessorWrapper wrapProcessor(Class processorTypeToWrap, Class expectedThrownException) { + + if (processorTypeToWrap == null) { + throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("type")); + } + + if (expectedThrownException == null) { + throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("expected exception")); + } + + try { + return new AnnotationProcessorWrapper(processorTypeToWrap.getDeclaredConstructor().newInstance(), expectedThrownException); + } catch (Exception e) { + throw new IllegalArgumentException(Constants.Messages.IAE_CANNOT_INSTANTIATE_PROCESSOR.produceMessage(processorTypeToWrap.getCanonicalName()), e); + } + + } + + + static Set getWrappedProcessors(CuteApi.CompilerTestBB compilerTestBB) { + + // return cached wrapped processors if available + + + Set wrappedProcessors = new HashSet<>(); + + + // need to add unit test processor + + + // TODO: THIS CASE HANDLES PROCESSOR INSTANCES - NORMALLY ONLY USED IN UNIT TESTS ?!? + /*- + for (Processor processor : compilerTestBB.processors()) { + + wrappedProcessors.add(AnnotationProcessorWrapper.wrapProcessor(processor, expectedThrownException)); + + } + */ + if (compilerTestBB.testType() == CuteApi.TestType.UNIT && compilerTestBB.unitTest() != null) { + Processor processor = null; + + // This is kind of difficult... + // must determine which annotation must be used as trigger and for scanning + // 1. passed in class - in this case the PassIn or annotationForScan must be used for scanning, DEFAULT ANNOTATION must be used as entry point + // 2. Pass in by source - in this case annotationForScan isn't used, just PassIn or annotationForScan if set + // 3. Implicit PassIn - just the default Source and Entry Point is available TestAnnotation Must be used + + if (compilerTestBB.unitTest() instanceof UnitTest) { + if (compilerTestBB.passInConfiguration() != null && compilerTestBB.passInConfiguration().getPassedInClass() != null) { + + // This is correct: DEFAULT AS ENTRY POINT AND PASSIN OR ANNOTATIONFORSCAN for scanning + processor = new UnitTestAnnotationProcessorClassWithPassIn<>( + compilerTestBB.passInConfiguration().getPassedInClass(), + compilerTestBB.passInConfiguration().getAnnotationToScanFor() != null ? compilerTestBB.passInConfiguration().getAnnotationToScanFor() : PassIn.class, + (UnitTest) compilerTestBB.unitTest()); + + } else { + // This is the legacy case + processor = new UnitTestAnnotationProcessorClass<>( + compilerTestBB.passInConfiguration() != null && compilerTestBB.passInConfiguration().getAnnotationToScanFor() != null ? compilerTestBB.passInConfiguration().getAnnotationToScanFor() : (compilerTestBB.passInConfiguration() != null && compilerTestBB.passInConfiguration().getPassInElement() ? PassIn.class : Constants.DEFAULT_ANNOTATION ), + (UnitTest) compilerTestBB.unitTest()); + } + + } else if (compilerTestBB.unitTest() instanceof UnitTestWithoutPassIn) { + + processor = new UnitTestAnnotationProcessorClassWithoutPassIn( + Constants.DEFAULT_ANNOTATION, + (UnitTestWithoutPassIn) compilerTestBB.unitTest()); + + } else if (compilerTestBB.unitTest() instanceof UnitTestForTestingAnnotationProcessors) { + + Processor processorUnderTest = null; + try { + processorUnderTest = compilerTestBB.passInConfiguration().getPassedInProcessor().getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new IllegalArgumentException(Constants.Messages.IAE_CANNOT_INSTANTIATE_PROCESSOR.produceMessage(compilerTestBB.passInConfiguration().getPassedInProcessor().getCanonicalName())); + } + + if (compilerTestBB.passInConfiguration() != null && compilerTestBB.passInConfiguration().getPassedInClass() != null) { + processor = new UnitTestAnnotationProcessorClassForTestingAnnotationProcessorsWithPassIn<>( + processorUnderTest, + Constants.DEFAULT_ANNOTATION, + compilerTestBB.passInConfiguration().getPassedInClass(), + compilerTestBB.passInConfiguration().getAnnotationToScanFor() != null ? compilerTestBB.passInConfiguration().getAnnotationToScanFor() : PassIn.class, + (UnitTestForTestingAnnotationProcessors) compilerTestBB.unitTest() + + ); + } else { + processor = new UnitTestAnnotationProcessorClassForTestingAnnotationProcessors<>( + processorUnderTest, + compilerTestBB.passInConfiguration().getAnnotationToScanFor() != null ? compilerTestBB.passInConfiguration().getAnnotationToScanFor() : (compilerTestBB.passInConfiguration().getPassInElement() ? PassIn.class : Constants.DEFAULT_ANNOTATION ), + (UnitTestForTestingAnnotationProcessors) compilerTestBB.unitTest()); + } + + + } else if (compilerTestBB.unitTest() instanceof UnitTestForTestingAnnotationProcessorsWithoutPassIn) { + + Processor processorUnderTest = null; + try { + processorUnderTest = compilerTestBB.passInConfiguration().getPassedInProcessor().getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw new IllegalArgumentException(Constants.Messages.IAE_CANNOT_INSTANTIATE_PROCESSOR.produceMessage(compilerTestBB.passInConfiguration().getPassedInProcessor().getCanonicalName())); + } + + processor = new UnitTestAnnotationProcessorClassForTestingAnnotationProcessorsWithoutPassIn<>( + processorUnderTest, + Constants.DEFAULT_ANNOTATION, + (UnitTestForTestingAnnotationProcessorsWithoutPassIn) compilerTestBB.unitTest()); + + } + + if (processor != null) { + wrappedProcessors.add(AnnotationProcessorWrapper.wrapProcessor(processor, compilerTestBB.getExceptionIsThrown())); + } + } + + // Configured processors by class + for (Class processorType : compilerTestBB.processors()) { + + try { + Processor processor = processorType.getDeclaredConstructor().newInstance(); + + wrappedProcessors.add(AnnotationProcessorWrapper.wrapProcessor(processor, compilerTestBB.getExceptionIsThrown())); + + } catch (Exception e) { + throw new IllegalArgumentException("Passed processor " + processorType.getCanonicalName() + " cannot be instantiated.", e); + } + + } + + // TODO: CURRENTLY NOT IMPLEMENTED WITH NEW FLUENT API + /*- + for (CompileTestConfiguration.ProcessorWithExpectedException processor : this.processorsWithExpectedExceptions) { + + wrappedProcessors.add(AnnotationProcessorWrapper.wrapProcessor(processor.processorType, processor.throwable != null ? processor.throwable : expectedThrownException)); + + } + */ + + + return wrappedProcessors; + + } + +} diff --git a/cute/src/main/java/io/toolisticon/cute/impl/CommonUtilities.java b/cute/src/main/java/io/toolisticon/cute/CommonUtilities.java similarity index 90% rename from cute/src/main/java/io/toolisticon/cute/impl/CommonUtilities.java rename to cute/src/main/java/io/toolisticon/cute/CommonUtilities.java index 186c89b..1c4e3b9 100644 --- a/cute/src/main/java/io/toolisticon/cute/impl/CommonUtilities.java +++ b/cute/src/main/java/io/toolisticon/cute/CommonUtilities.java @@ -1,11 +1,11 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; import java.util.Random; /** * Some common utility functions. */ -public final class CommonUtilities { +final class CommonUtilities { /** * Hidden constructor. diff --git a/cute/src/main/java/io/toolisticon/cute/impl/CompilationResult.java b/cute/src/main/java/io/toolisticon/cute/CompilationResult.java similarity index 97% rename from cute/src/main/java/io/toolisticon/cute/impl/CompilationResult.java rename to cute/src/main/java/io/toolisticon/cute/CompilationResult.java index 485cdc3..7f6226a 100644 --- a/cute/src/main/java/io/toolisticon/cute/impl/CompilationResult.java +++ b/cute/src/main/java/io/toolisticon/cute/CompilationResult.java @@ -1,4 +1,4 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; diff --git a/cute/src/main/java/io/toolisticon/cute/impl/CompileTest.java b/cute/src/main/java/io/toolisticon/cute/CompileTest.java similarity index 73% rename from cute/src/main/java/io/toolisticon/cute/impl/CompileTest.java rename to cute/src/main/java/io/toolisticon/cute/CompileTest.java index 7083548..8044c88 100644 --- a/cute/src/main/java/io/toolisticon/cute/impl/CompileTest.java +++ b/cute/src/main/java/io/toolisticon/cute/CompileTest.java @@ -1,9 +1,5 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; -import io.toolisticon.cute.Constants; -import io.toolisticon.cute.FailingAssertionException; -import io.toolisticon.cute.GeneratedFileObjectMatcher; -import io.toolisticon.cute.InvalidTestConfigurationException; import io.toolisticon.cute.extension.api.AssertionSpiServiceLocator; import io.toolisticon.cute.extension.api.ModuleSupportSpi; import io.toolisticon.cute.extension.api.ModuleSupportSpiServiceLocator; @@ -16,6 +12,8 @@ import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -23,20 +21,24 @@ /** * Implementation of a compile test. */ -public class CompileTest { +class CompileTest { // Messages - private final CompileTestConfiguration compileTestConfiguration; + private final CuteApi.CompilerTestBB compileTestConfiguration; + + private final Set wrappedAnnotationProcessors; /** * Main constructor. * * @param compileTestConfiguration the configuration used during tests. */ - public CompileTest(final CompileTestConfiguration compileTestConfiguration) { + public CompileTest(final CuteApi.CompilerTestBB compileTestConfiguration) { this.compileTestConfiguration = compileTestConfiguration; + this.wrappedAnnotationProcessors = AnnotationProcessorWrapper.getWrappedProcessors(compileTestConfiguration); + } /** @@ -50,25 +52,25 @@ public void executeTest() { try { // Execute tests now - compilationResult = compile(compileTestConfiguration); + compilationResult = compile(compileTestConfiguration, wrappedAnnotationProcessors); // Check if all processors have been applied checkIfProcessorsHaveBeenApplied(compilationResult.getDiagnostics()); // check if error messages and shouldSucceed aren't set contradictory - if (compileTestConfiguration.getCompilationShouldSucceed() != null - && compileTestConfiguration.getCompilationShouldSucceed() + if (compileTestConfiguration.compilationSucceeded() != null + && compileTestConfiguration.compilationSucceeded() && compileTestConfiguration.countErrorMessageChecks() > 0) { throw new InvalidTestConfigurationException(Constants.Messages.MESSAGE_COMPILATION_SHOULD_SUCCEED_AND_ERROR_MESSAGE_EXPECTED.produceMessage()); } // Check if compilation succeeded - if (compileTestConfiguration.getCompilationShouldSucceed() != null && !compileTestConfiguration.getCompilationShouldSucceed().equals(compilationResult.getCompilationSucceeded())) { + if (compileTestConfiguration.compilationSucceeded() != null && !compileTestConfiguration.compilationSucceeded().equals(compilationResult.getCompilationSucceeded())) { throw new FailingAssertionException( - compileTestConfiguration.getCompilationShouldSucceed() + compileTestConfiguration.compilationSucceeded() ? Constants.Messages.MESSAGE_COMPILATION_SHOULD_HAVE_SUCCEEDED_BUT_FAILED.produceMessage() + "\nERRORS:\n" + CompileTestUtilities.getMessages(compilationResult.getDiagnostics(), Diagnostic.Kind.ERROR) : Constants.Messages.MESSAGE_COMPILATION_SHOULD_HAVE_FAILED_BUT_SUCCEEDED.produceMessage() ); @@ -80,8 +82,8 @@ public void executeTest() { checkMessages(compilationResult.getDiagnostics()); - for (CompileTestConfiguration.GeneratedJavaFileObjectCheck generatedJavaFileObjectCheck : this.compileTestConfiguration.getGeneratedJavaFileObjectChecks()) { - if (CompileTestConfiguration.FileObjectCheckType.EXISTS.equals(generatedJavaFileObjectCheck.getCheckType())) { + for (CuteApi.GeneratedJavaFileObjectCheckBB generatedJavaFileObjectCheck : this.compileTestConfiguration.javaFileObjectChecks()) { + if (CuteApi.FileObjectCheckType.EXISTS.equals(generatedJavaFileObjectCheck.getCheckType())) { if (!compilationResult.getCompileTestFileManager().existsExpectedJavaFileObject(generatedJavaFileObjectCheck.getLocation(), generatedJavaFileObjectCheck.getClassName(), generatedJavaFileObjectCheck.getKind())) { throw new FailingAssertionException(Constants.Messages.MESSAGE_JFO_DOESNT_EXIST.produceMessage(getJavaFileObjectInfoString(generatedJavaFileObjectCheck))); } else { @@ -122,9 +124,9 @@ public void executeTest() { } - for (CompileTestConfiguration.GeneratedFileObjectCheck generatedFileObjectCheck : this.compileTestConfiguration.getGeneratedFileObjectChecks()) { + for (CuteApi.GeneratedFileObjectCheckBB generatedFileObjectCheck : this.compileTestConfiguration.fileObjectChecks()) { - if (CompileTestConfiguration.FileObjectCheckType.EXISTS.equals(generatedFileObjectCheck.getCheckType())) { + if (CuteApi.FileObjectCheckType.EXISTS.equals(generatedFileObjectCheck.getCheckType())) { if (!compilationResult.getCompileTestFileManager().existsExpectedFileObject(generatedFileObjectCheck.getLocation(), generatedFileObjectCheck.getPackageName(), generatedFileObjectCheck.getRelativeName())) { throw new FailingAssertionException(Constants.Messages.MESSAGE_FO_DOESNT_EXIST.produceMessage(getFileObjectInfoString(generatedFileObjectCheck))); @@ -171,6 +173,12 @@ public void executeTest() { } catch (RuntimeException e) { + if (e.getCause() != null && AssertionError.class.isAssignableFrom(e.getCause().getClass())) { + FailingAssertionException failingAssertionException = new FailingAssertionException(e.getMessage(), e.getCause()); + AssertionSpiServiceLocator.locate().fail(e.getCause().getMessage() + "\n" + DebugOutputGenerator.getDebugOutput(compilationResult, compileTestConfiguration, failingAssertionException)); + throw (failingAssertionException); + } + if (e.getCause() != null && FailingAssertionException.class.isAssignableFrom(e.getCause().getClass())) { // now trigger failing assertion, but also enrich message with debug output AssertionSpiServiceLocator.locate().fail(e.getCause().getMessage() + "\n" + DebugOutputGenerator.getDebugOutput(compilationResult, compileTestConfiguration, (FailingAssertionException) e.getCause())); @@ -185,11 +193,11 @@ public void executeTest() { } - static String getJavaFileObjectInfoString(CompileTestConfiguration.GeneratedJavaFileObjectCheck generatedJavaFileObjectCheck) { + static String getJavaFileObjectInfoString(CuteApi.GeneratedJavaFileObjectCheckBB generatedJavaFileObjectCheck) { return generatedJavaFileObjectCheck.getLocation() + "; " + generatedJavaFileObjectCheck.getClassName() + "; " + generatedJavaFileObjectCheck.getKind(); } - static String getFileObjectInfoString(CompileTestConfiguration.GeneratedFileObjectCheck generatedFileObjectCheck) { + static String getFileObjectInfoString(CuteApi.GeneratedFileObjectCheckBB generatedFileObjectCheck) { return generatedFileObjectCheck.getLocation() + "; " + generatedFileObjectCheck.getPackageName() + "; " + generatedFileObjectCheck.getRelativeName(); } @@ -199,7 +207,7 @@ static String getFileObjectInfoString(CompileTestConfiguration.GeneratedFileObje * @param compileTestConfiguration the compile-test configuration to use * @return the compilation result */ - public static CompilationResult compile(CompileTestConfiguration compileTestConfiguration) { + public static CompilationResult compile(CuteApi.CompilerTestBB compileTestConfiguration, Set wrappedAnnotationProcessors) { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector diagnostics = new DiagnosticCollector<>(); @@ -214,17 +222,17 @@ public static CompilationResult compile(CompileTestConfiguration compileTestConf null, javaFileManager, diagnostics, - compileTestConfiguration.getCompilerOptions().isEmpty() ? null : compileTestConfiguration.getNormalizedCompilerOptions(), + compileTestConfiguration.compilerOptions().isEmpty() ? null : compileTestConfiguration.getNormalizedCompilerOptions(), null, - compileTestConfiguration.getSourceFiles()); + compileTestConfiguration.sourceFiles()); - compilationTask.setProcessors(compileTestConfiguration.getWrappedProcessors()); + compilationTask.setProcessors(wrappedAnnotationProcessors); // handle java 9 module support via SPI to be backward compatible with older Java versions prior to java 9 if (!Java9SupportCheck.UNSUPPORTED_JAVA_VERSION) { ModuleSupportSpi moduleService = ModuleSupportSpiServiceLocator.locate(); if (moduleService != null) { - moduleService.applyModulePath(stdJavaFileManager, compilationTask, compileTestConfiguration.getModules()); + moduleService.applyModulePath(stdJavaFileManager, compilationTask, compileTestConfiguration.modules()); } } @@ -244,7 +252,7 @@ void checkIfProcessorsHaveBeenApplied(DiagnosticCollector diagno Set messages = CompileTestUtilities.getMessages(diagnostics, Diagnostic.Kind.NOTE); outer: - for (AnnotationProcessorWrapper processor : compileTestConfiguration.getWrappedProcessors()) { + for (AnnotationProcessorWrapper processor : this.wrappedAnnotationProcessors) { for (String message : messages) { if (message.equals(processor.getProcessorWasAppliedMessage())) { @@ -265,49 +273,49 @@ void checkIfProcessorsHaveBeenApplied(DiagnosticCollector diagno void checkMessages(DiagnosticCollector diagnostics) { // Just check messages of matching kind - Map> compileMessageChecks = compileTestConfiguration.getCompilerMessageCheckByKindMap(); + Map> compileMessageChecks = getCompilerMessageCheckByKindMap(compileTestConfiguration); - for (Map.Entry> entry : compileMessageChecks.entrySet()) { + for (Map.Entry> entry : compileMessageChecks.entrySet()) { Set filteredDiagnostics = CompileTestUtilities.getDiagnosticByKind(diagnostics, entry.getKey()); outer: - for (CompileTestConfiguration.CompilerMessageCheck messageToCheck : entry.getValue()) { + for (CuteApi.CompilerMessageCheckBB messageToCheck : entry.getValue()) { for (Diagnostic element : filteredDiagnostics) { - String localizedMessage = element.getMessage(messageToCheck.getLocale()); + String localizedMessage = element.getMessage(messageToCheck.withLocale()); // Check message - switch (messageToCheck.getComparisonKind()) { + switch (messageToCheck.getComparisonType()) { case EQUALS: { - if (!localizedMessage.equals(messageToCheck.getExpectedMessage())) { + if (!localizedMessage.equals(messageToCheck.getSearchString().get(0))) { continue; } break; } case CONTAINS: default: { - if (!localizedMessage.contains(messageToCheck.getExpectedMessage())) { + if (!messageToCheck.getSearchString().stream().allMatch(e -> localizedMessage.contains(e))) { continue; } } } // check source - if (messageToCheck.getSource() != null && !messageToCheck.getSource().equals(((FileObject) element.getSource()).getName())) { + if (messageToCheck.atSource() != null && !messageToCheck.atSource().equals(((FileObject) element.getSource()).getName())) { continue; } // check line - if (messageToCheck.getLineNumber() != null && element.getLineNumber() != messageToCheck.getLineNumber()) { + if (messageToCheck.atLine() != null && element.getLineNumber() != messageToCheck.atLine()) { continue; } // check column - if (messageToCheck.getColumnNumber() != null && element.getColumnNumber() != messageToCheck.getColumnNumber()) { + if (messageToCheck.atColumn() != null && element.getColumnNumber() != messageToCheck.atColumn()) { continue; } @@ -317,7 +325,7 @@ void checkMessages(DiagnosticCollector diagnostics) { } // Not found ==> assertion fails - throw new FailingAssertionException(Constants.Messages.MESSAGE_HAVENT_FOUND_MESSSAGE.produceMessage(messageToCheck.getExpectedMessage(), messageToCheck.getKind().name())); + throw new FailingAssertionException(Constants.Messages.MESSAGE_HAVENT_FOUND_MESSSAGE.produceMessage(messageToCheck.getSearchString(), messageToCheck.getKind().name())); } @@ -326,4 +334,22 @@ void checkMessages(DiagnosticCollector diagnostics) { } + public Map> getCompilerMessageCheckByKindMap(CuteApi.CompilerTestBB compilerTestBB) { + Map> map = new HashMap<>(); + + for (CuteApi.CompilerMessageCheckBB compilerMessageCheck : compilerTestBB.compilerMessageChecks()) { + + List checkByKindList = map.get(compilerMessageCheck.getKind()); + if (checkByKindList == null) { + checkByKindList = new ArrayList<>(); + map.put(Diagnostic.Kind.valueOf(compilerMessageCheck.getKind().name()), checkByKindList); + + } + + checkByKindList.add(compilerMessageCheck); + } + + return map; + } + } diff --git a/cute/src/main/java/io/toolisticon/cute/impl/CompileTestFileManager.java b/cute/src/main/java/io/toolisticon/cute/CompileTestFileManager.java similarity index 99% rename from cute/src/main/java/io/toolisticon/cute/impl/CompileTestFileManager.java rename to cute/src/main/java/io/toolisticon/cute/CompileTestFileManager.java index c16352d..afe8823 100644 --- a/cute/src/main/java/io/toolisticon/cute/impl/CompileTestFileManager.java +++ b/cute/src/main/java/io/toolisticon/cute/CompileTestFileManager.java @@ -1,4 +1,4 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; import io.toolisticon.cute.Constants; diff --git a/cute/src/main/java/io/toolisticon/cute/impl/CompileTestUtilities.java b/cute/src/main/java/io/toolisticon/cute/CompileTestUtilities.java similarity index 98% rename from cute/src/main/java/io/toolisticon/cute/impl/CompileTestUtilities.java rename to cute/src/main/java/io/toolisticon/cute/CompileTestUtilities.java index 3517ec2..f7de0d6 100644 --- a/cute/src/main/java/io/toolisticon/cute/impl/CompileTestUtilities.java +++ b/cute/src/main/java/io/toolisticon/cute/CompileTestUtilities.java @@ -1,4 +1,4 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; import javax.annotation.processing.Processor; diff --git a/cute/src/main/java/io/toolisticon/cute/Constants.java b/cute/src/main/java/io/toolisticon/cute/Constants.java index c442858..adbaddd 100644 --- a/cute/src/main/java/io/toolisticon/cute/Constants.java +++ b/cute/src/main/java/io/toolisticon/cute/Constants.java @@ -35,7 +35,7 @@ public String getMessagePattern(){ public final static Message UNIT_TEST_PRECONDITION_INCOMPATIBLE_ELEMENT_TYPE = new Message("PRECONDITION : Processed Element type doesn't match the one expected by your unit test processor"); public final static Message UNIT_TEST_PRECONDITION_MUST_FIND_ONE_ELEMENT = new Message("PRECONDITION: Expected to find at an element annotated with %s in processed sources files."); public final static Message UNIT_TEST_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT = new Message("PRECONDITION: Expected to find exactly one element annotated with %s in processed sources files. Please add PassIn annotation to the one Element you want to pass in."); - public final static Message UNIT_TEST_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT_WITH_PASSIN_ANNOTATION = new Message("PRECONDITION: Expected to find exactly one element annotated with %s and " + PassIn.class.getName() + " in processed sources files. Found more than one element annotated with " + PassIn.class.getName() +"."); + public final static Message UNIT_TEST_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT_WITH_PASSIN_ANNOTATION = new Message("PRECONDITION: Expected to find exactly one element annotated with " + PassIn.class.getName() + " in processed sources files, but found more than one element annotated with " + PassIn.class.getName() +"."); public final static Message UNIT_TEST_PASS_IN_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT = new Message("PRECONDITION: Expected to find exactly one element annotated with %s in passed in class %s"); diff --git a/cute/src/main/java/io/toolisticon/cute/CuteApi.java b/cute/src/main/java/io/toolisticon/cute/CuteApi.java new file mode 100644 index 0000000..f02bb3a --- /dev/null +++ b/cute/src/main/java/io/toolisticon/cute/CuteApi.java @@ -0,0 +1,1175 @@ +package io.toolisticon.cute; + + +import io.toolisticon.cute.matchers.CoreGeneratedFileObjectMatchers; +import io.toolisticon.fluapigen.api.FluentApi; +import io.toolisticon.fluapigen.api.FluentApiBackingBean; +import io.toolisticon.fluapigen.api.FluentApiBackingBeanField; +import io.toolisticon.fluapigen.api.FluentApiBackingBeanMapping; +import io.toolisticon.fluapigen.api.FluentApiCommand; +import io.toolisticon.fluapigen.api.FluentApiConverter; +import io.toolisticon.fluapigen.api.FluentApiImplicitValue; +import io.toolisticon.fluapigen.api.FluentApiInterface; +import io.toolisticon.fluapigen.api.FluentApiParentBackingBeanMapping; +import io.toolisticon.fluapigen.api.FluentApiRoot; +import io.toolisticon.fluapigen.api.MappingAction; +import io.toolisticon.fluapigen.api.TargetBackingBean; +import io.toolisticon.fluapigen.validation.api.NotNull; + +import javax.annotation.processing.Processor; +import javax.lang.model.element.Element; +import javax.tools.FileObject; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.StandardLocation; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +/** + * This class defines the fluent api used to set up and execute black box and unit compile tests. + * Black box tests are compiling source files by using a processor and allow checking its outcome. + * Unit tests are allowing you to unit test annotation processor related code by providing a compile-time testing environment. + * + * @author Tobias Stamann + */ +@FluentApi("Cute") +public class CuteApi { + + @FluentApiBackingBean + public interface CompilerTestBB { + TestType testType(); + + UnitTestType getPassInType(); + + + List> processors(); + + List compilerOptions(); + + Set sourceFiles(); + + Set modules(); + + @FluentApiBackingBeanField("compilationSucceeded") + Boolean compilationSucceeded(); + + @FluentApiBackingBeanField("exceptionIsThrown") + Class getExceptionIsThrown(); + + UnitTestBase unitTest(); + + PassInConfigurationBB passInConfiguration(); + + @FluentApiBackingBeanField("compileMessageChecks") + List compilerMessageChecks(); + + @FluentApiBackingBeanField("javaFileObjectChecks") + List javaFileObjectChecks(); + + @FluentApiBackingBeanField("fileObjectChecks") + List fileObjectChecks(); + + default long countErrorMessageChecks() { + long count = 0; + + for (CuteApi.CompilerMessageCheckBB compilerMessageCheck : compilerMessageChecks()) { + if (CompilerMessageKind.ERROR.toString().equals(compilerMessageCheck.getKind().name())) { + count++; + } + } + + return count; + } + + default List getNormalizedCompilerOptions() { + + List normalizedCompilerOptions = new ArrayList<>(); + + for (String compilerOption : compilerOptions()) { + + if (compilerOption != null) { + for (String tokenizedCompilerOption : compilerOption.split("[ ]+")) { + if (!tokenizedCompilerOption.isEmpty()) { + normalizedCompilerOptions.add(tokenizedCompilerOption); + } + } + } + } + + return normalizedCompilerOptions; + + } + + + } + + + @FluentApiBackingBean + public interface PassInConfigurationBB { + + /** + * This is a marker if passing in of Elements should be used. + * In this case exactly one PassIn annotation must be present in passed in Class or in added source files. + * + * @return true if unit test should pass in an element, otherwise false + */ + @FluentApiBackingBeanField(value = "passInElement", initValue = "false") + boolean getPassInElement(); + + @FluentApiBackingBeanField("passedInClass") + Class getPassedInClass(); + + @FluentApiBackingBeanField("annotationToScanFor") + Class getAnnotationToScanFor(); + + @FluentApiBackingBeanField("passedInProcessor") + Class getPassedInProcessor(); + } + + @FluentApiBackingBean + public interface CompilerMessageCheckBB { + + @FluentApiBackingBeanField("compilerMessageScope") + CompilerMessageKind getKind(); + + @FluentApiBackingBeanField("compilerMessageComparisonType") + CompilerMessageComparisonType getComparisonType(); + + @FluentApiBackingBeanField("searchString") + List getSearchString(); + + @FluentApiBackingBeanField("atLine") + Integer atLine(); + + @FluentApiBackingBeanField("atColumn") + Integer atColumn(); + + @FluentApiBackingBeanField("atSource") + String atSource(); + + @FluentApiBackingBeanField("withLocale") + Locale withLocale(); + + } + + + public enum TestType { + UNIT, BLACK_BOX + } + + public enum UnitTestType { + NO_PASS_IN, ELEMENT, PROCESSOR, ELEMENT_AND_PROCESSOR + } + + public enum CompilerMessageComparisonType { + CONTAINS, EQUALS; + } + + public enum CompilerMessageKind { + NOTE, WARNING, MANDATORY_WARNING, ERROR; + } + + + public enum FileObjectCheckType { + EXISTS, DOESNT_EXIST + } + + @FluentApiBackingBean + public interface GeneratedJavaFileObjectCheckBB { + + @FluentApiBackingBeanField("checkType") + FileObjectCheckType getCheckType(); + + @FluentApiBackingBeanField("location") + JavaFileManager.Location getLocation(); + + @FluentApiBackingBeanField("className") + String getClassName(); + + @FluentApiBackingBeanField("kind") + JavaFileObject.Kind getKind(); + + @FluentApiBackingBeanField("generatedFileObjectMatcher") + GeneratedFileObjectMatcher getGeneratedFileObjectMatcher(); + } + + @FluentApiBackingBean + public interface GeneratedFileObjectCheckBB { + + @FluentApiBackingBeanField("checkType") + FileObjectCheckType getCheckType(); + + @FluentApiBackingBeanField("location") + JavaFileManager.Location getLocation(); + + @FluentApiBackingBeanField("packageName") + String getPackageName(); + + @FluentApiBackingBeanField("relativeName") + String getRelativeName(); + + @FluentApiBackingBeanField("generatedFileObjectMatcher") + GeneratedFileObjectMatcher[] getGeneratedFileObjectMatchers(); + + } + + // -------------------------------------------------------------------- + // -------------------------------------------------------------------- + // Fluent API Interfaces + // -------------------------------------------------------------------- + // -------------------------------------------------------------------- + + /** + * This is the root interface. + * It allows the selection of the test type. + * All of its methods will be statically linked in the {@link Cute} fluent api implementation class. + */ + @FluentApiInterface(CompilerTestBB.class) + @FluentApiRoot + public interface MyRootInterface { + + /** + * This method can be used to start a unit test. + * + * @return the next fluent api interface + */ + @FluentApiImplicitValue(id = "testType", value = "UNIT") + @FluentApiImplicitValue(id = "sourceFiles", value = Constants.DEFAULT_UNIT_TEST_SOURCE_FILE, converter = ResourceToFileObjectConverter.class) + UnitTestRootInterface unitTest(); + + + /** + * This method can be used to start a black-box test (aka compile-test). + * Black-box test are compiling some source files with an annotation processor and can check the compilation's outcome. + * + * @return + */ + @FluentApiImplicitValue(id = "testType", value = "BLACK_BOX") + BlackBoxTestRootInterface blackBoxTest(); + + + } + + /** + * A converter to read a JavaFileObject for a resource location string. + */ + public static class ResourceToFileObjectConverter implements FluentApiConverter { + @Override + public JavaFileObject convert(String resource) { + return JavaFileObjectUtils.readFromResource(resource); + } + } + + // -------------------------------------------------------------------- + // Black Box Test Interfaces + // -------------------------------------------------------------------- + + @FluentApiInterface(CompilerTestBB.class) + public interface BlackBoxTestRootInterface { + + /** + * Allows you to traverse to the given section which allows you to configure the annotation processor, source files,... + * + * @return the next fluent interface + */ + BlackBoxTestProcessorsInterface given(); + + } + + @FluentApiInterface(CompilerTestBB.class) + public interface BlackBoxTestProcessorsInterface { + + /** + * Allows you to add annotation processors used at black-box tests compilation. + * By passing no processors compilation will be done without using processors. + * + * @param processors the annotation processors to use. Empty value will compile the source files without using processors, null values are prohibited and will lead to a {@link io.toolisticon.fluapigen.validation.api.ValidatorException}. + * @return the next fluent interface + */ + BlackBoxTestSourceFilesInterface processors(@FluentApiBackingBeanMapping(value = "processors") @NotNull Class... processors); + + /** + * More obvious method not to use processors during compilation. + * Same as calling processors without values. + * + * @return the next fluent interface + */ + default BlackBoxTestSourceFilesInterface noProcessors() { + return processors(); + } + + } + + @FluentApiInterface(CompilerTestBB.class) + public interface BlackBoxTestSourceFilesInterface { + + /** + * Adds source files as JavaFileObjects. + * The {@link JavaFileObjectUtils} class can be used to provide source files. + * + * @param sourceFile the source files to use during compilation + * @return the next fluent interface + */ + BlackBoxTestFinalGivenInterface andSourceFiles(@FluentApiBackingBeanMapping(value = "sourceFiles", action = MappingAction.ADD) @NotNull JavaFileObject... sourceFile); + + /** + * Add sources files by reading them from resource Strings. + * + * @param resources the resource paths used to read the source files from + * @return the next fluent interface + */ + // TODO: A validation if passed resource locations are correct would be good + default BlackBoxTestFinalGivenInterface andSourceFiles(String... resources) { + return andSourceFiles(Arrays.stream(resources).map(e -> JavaFileObjectUtils.readFromResource(e)).toArray(JavaFileObject[]::new)); + } + + /** + * Adds a source file by providing a fully qualified class name and the class code provided as a String. + * + * @param className the fully qualified name of the class + * @param content the source code of the class as a string. Of course fully qualified class name must match className parameter. + * @return the next fluent interface + */ + default BlackBoxTestFinalGivenInterface andSourceFile(String className, String content) { + return andSourceFiles(JavaFileObjectUtils.readFromString(className, content)); + } + + + } + + @FluentApiInterface(CompilerTestBB.class) + public interface BlackBoxTestFinalGivenInterface { + + /** + * Adds source files as JavaFileObjects. + * The {@link JavaFileObjectUtils} class can be used to provide source files. + * + * @param sourceFile the source files to use during compilation + * @return the next fluent interface + */ + BlackBoxTestFinalGivenInterface andSourceFiles(@FluentApiBackingBeanMapping(value = "sourceFiles", action = MappingAction.ADD) JavaFileObject... sourceFile); + + /** + * Add sources files by reading them from resource Strings. + * + * @param resources the resource paths used to read the source files from + * @return the next fluent interface + */ + default BlackBoxTestFinalGivenInterface andSourceFiles(@NotNull String... resources) { + return andSourceFiles(Arrays.stream(resources).map(e -> JavaFileObjectUtils.readFromResource(e)).toArray(String[]::new)); + } + + /** + * Adds a source file by providing a fully qualified class name and the class code provided as a String. + * + * @param className the fully qualified name of the class + * @param content the source code of the class as a string. Of course fully qualified class name must match className parameter. + * @return the next fluent interface + */ + default BlackBoxTestFinalGivenInterface andSourceFile(String className, String content) { + return andSourceFiles(JavaFileObjectUtils.readFromString(className, content)); + } + + /** + * Use compiler options. + * Options with parameters can, but must not be split over two consecutive Strings. + * Those options can be put in one single String (e.g. "-source 1.7" or "-target 1.7"). + * + * @param compilerOptions the options to use + * @return the next builder instance + */ + BlackBoxTestFinalGivenInterface andUseCompilerOptions(@FluentApiBackingBeanMapping(value = "compilerOptions") @NotNull String... compilerOptions); + + /** + * Defines modules used during compilation. + * This configuration will be ignored for Java versions < 9. + * + * @param modules The modules to use during compilation + * @return the next builder instance + */ + BlackBoxTestFinalGivenInterface andUseModules(@FluentApiBackingBeanMapping(value = "modules") @NotNull String... modules); + + /** + * Traverses to the compilation result validation section. + * + * @return the next builder instance + */ + BlackBoxTestInterface whenCompiled(); + + /** + * Executes test without explicitly checking the outcome. + */ + @FluentApiCommand(ExecuteTestCommand.class) + @FluentApiImplicitValue(id = "compilationSucceeded", value = "true") + void executeTest(); + + } + + // -------------------------------------------------------------------- + // Unit Test Interfaces + // -------------------------------------------------------------------- + + @FluentApiInterface(CompilerTestBB.class) + public interface UnitTestRootInterface { + + /** + * Traverses to given section of unit test. + * Allows to add source files, to define compiler options and java modules. + * + * @return + */ + UnitTestGivenInterface given(); + + /** + * Starts when block for unit test. + *

+ * This allows pass in of an Element or a processor instance before defining the un it test. + * + * @return the next fluent api instance + */ + UnitTestWhenInterface when(); + + /** + * Directly defines unit test. Disables passing in of processor and Element. + * + * @return the next fluent api instance + */ + UnitTestInterface when(@FluentApiBackingBeanMapping(value = "unitTest", action = MappingAction.SET) @NotNull UnitTestWithoutPassIn unitTest); + + } + + @FluentApiInterface(CompilerTestBB.class) + public interface UnitTestGivenInterface { + + /** + * Use compiler options. + * Options with parameters can, but must not be split over two consecutive Strings. + * Those options can be put in one single String (e.g. "-source 1.7" or "-target 1.7"). + * + * @param compilerOptions the options to use + * @return the next builder instance + */ + UnitTestGivenInterface useCompilerOptions(@FluentApiBackingBeanMapping(value = "compilerOptions") @NotNull String... compilerOptions); + + /** + * Defines modules used during compilation. + * This configuration will be ignored for Java versions < 9. + * + * @param modules The modules to use during compilation + * @return the next builder instance + */ + UnitTestGivenInterface useModules(@FluentApiBackingBeanMapping(value = "modules") @NotNull String... modules); + + /** + * Convenience method to add multiple source files via resource strings. + * + * @param resources the source file resource strings + * @return the next builder instance + */ + default UnitTestGivenInterface useSourceFiles(String... resources) { + UnitTestGivenInterface next = this; + if (resources != null) { + for (String resource : resources) { + next = next.useSourceFile(resource); + } + } + return next; + } + + /** + * Adds a source file by its resource path string. + * + * @param resource the resource path string + * @return the next fluent interface + */ + default UnitTestGivenInterface useSourceFile(String resource) { + return useSourceFile(JavaFileObjectUtils.readFromResource(resource)); + } + + /** + * Adds a source file by its fully qualified class name and a source string. + * + * @param className the fully qualified class name + * @param content the source code of the class as a String + * @return the next fluent interface + */ + default UnitTestGivenInterface useSourceFile(String className, String content) { + return useSourceFile(JavaFileObjectUtils.readFromString(className, content)); + } + + /** + * Adds a source file as a JavaFileObject. + * Use {@link JavaFileObjectUtils} to provide JavaFileObjects. + * + * @param sourceFile the source file + * @return the next fluent interface + */ + UnitTestGivenInterface useSourceFile(@FluentApiBackingBeanMapping(value = "sourceFiles") @NotNull JavaFileObject sourceFile); + + + /** + * Traverse to when section to pass in an Element or a processor instant and to define the unit test scenario. + * + * @return the next fluent interface + */ + UnitTestWhenInterface when(); + + + } + + + @FluentApiInterface(CompilerTestBB.class) + public interface UnitTestWhenInterface { + + /** + * Passes in an Element. + * + * @return the next fluent interface + */ + PassInElementInterface passInElement(); + + /** + * Passes in a processor instance. + * Processor class must have an accessible noarg constructor. + * + * @param processorClass The processor type to create the instance for - must not be null and have an accessible no args constructor + * @param The processor type + * @return the next fluent interface + */ + PassInProcessorInterface passInProcessor(@FluentApiBackingBeanMapping(value = "passedInProcessor", target = TargetBackingBean.NEXT) @NotNull Class processorClass); + + /** + * Disables pass in of Element ant Processor and directly defines the unit test + * + * @param unitTest the unit test + * @return the next fluent interface + */ + UnitTestInterface unitTestWithoutPassIn(@FluentApiBackingBeanMapping(value = "unitTest", action = MappingAction.SET, target = TargetBackingBean.NEXT) @NotNull UnitTestWithoutPassIn unitTest); + + } + + @FluentApiInterface(CompilerTestBB.class) + public interface PassInElementInterface { + + /** + * Passes in an Element via a source String and fully qualified class name. + * The class must contain exactly one Element annotated with {@link PassIn} annotation. + * Passed in Element type can be declared via method type variable: prevInstance.<TypeElement>fromSourceString(...) + * + * @param className The fully qualified class name + * @param sourceString the source string of the class + * @param The type of the passed in Element + * @return the next fluent interface + */ + default PassInElementAndProcessorInterface fromSourceString(String className, String sourceString) { + return this.fromJavaFileObject(JavaFileObjectUtils.readFromString(className, sourceString)); + } + + /** + * Passes in an Element via the resource path String of a source file. + * The source file must contain exactly one Element annotated with {@link PassIn} annotation. + * Passed in Element type can be declared via method type variable: prevInstance.<TypeElement>fromSourceFile(...) + * + * @param resourceName The resource path String of the source file + * @param The type of the passed in Element + * @return the next fluent interface + */ + + default PassInElementAndProcessorInterface fromSourceFile(String resourceName) { + return this.fromJavaFileObject(JavaFileObjectUtils.readFromResource(resourceName)); + } + + /** + * Passes in an Element via a JavaFileObject representing a source file. + * The JavaFileObject must contain exactly one Element annotated with {@link PassIn} annotation. + * Passed in Element type can be declared via method type variable: prevInstance.<TypeElement>fromJavaFileObject(...) + * + * @param javaFileObject The JavaFileObject representing a source file + * @param The type of the passed in Element + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "passInElement", value = "true", target = TargetBackingBean.NEXT) + PassInElementAndProcessorInterface fromJavaFileObject(@FluentApiBackingBeanMapping(value = "sourceFiles", action = MappingAction.SET) @NotNull JavaFileObject javaFileObject); + + /** + * The Element will be passed in via a compiled class. + * Class must contain exactly one element annotated with {@link PassIn} annotation. + * Warning: All non-runtime annotations on the element won't be accessible!!! + * Use source file approach if you need to support non-runtime annotations. + * + * @param classToScanForElement the class to scan for Element + * @param the element type + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "passInElement", value = "true", target = TargetBackingBean.NEXT) + PassInElementAndProcessorInterface fromClass(@FluentApiBackingBeanMapping(value = "passedInClass", target = TargetBackingBean.NEXT) @NotNull Class classToScanForElement); + + /** + * The element will be passed in from given source files. Exactly one Source file must contain a PassIn annotation. + * This method should only be used, if non-runtime annotations are involved in unit tests. + * + * @param the Element type of passed in interface. + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "passInElement", value = "true", target = TargetBackingBean.NEXT) + PassInElementAndProcessorInterface fromGivenSourceFiles(); + + } + + @FluentApiInterface(PassInConfigurationBB.class) + public interface PassInProcessorInterface { + + /** + * Passes in an Element. + * + * @return the next fluent interface + */ + PassInProcessorAndElementInterface andPassInElement(); + + /** + * Define unit test. + * + * @param unitTest the Unit test + * @return the next fluent inteface + */ + @FluentApiImplicitValue(id = "getPassInType", value = "PROCESSOR", target = TargetBackingBean.NEXT) + @FluentApiParentBackingBeanMapping(value = "passInConfiguration") + UnitTestInterface intoUnitTest(@FluentApiBackingBeanMapping(value = "unitTest", action = MappingAction.SET, target = TargetBackingBean.NEXT) @NotNull UnitTestForTestingAnnotationProcessorsWithoutPassIn unitTest); + } + + + @FluentApiInterface(PassInConfigurationBB.class) + public interface PassInElementAndProcessorInterface { + + /** + * Pass in processor instance. + * + * @param processorClass The processor type. The type must have an accessible noarg constructor + * @param The type of the processor + * @return the next fluent interface + */ + @FluentApiParentBackingBeanMapping(value = "passInConfiguration") + UnitTestWhenWithPassedInElementAndProcessorInterface andPassInProcessor(@FluentApiBackingBeanMapping(value = "passedInProcessor") @NotNull Class processorClass); + + /** + * Defines the unit test. + * + * @param unitTest the unit test + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "getPassInType", value = "ELEMENT", target = TargetBackingBean.NEXT) + @FluentApiParentBackingBeanMapping(value = "passInConfiguration") + UnitTestInterface intoUnitTest(@FluentApiBackingBeanMapping(value = "unitTest", action = MappingAction.SET, target = TargetBackingBean.NEXT) @NotNull UnitTest unitTest); + } + + @FluentApiInterface(PassInConfigurationBB.class) + public interface PassInProcessorAndElementInterface { + + /** + * Passes in an Element via a source String and fully qualified class name. + * The class must contain exactly one Element annotated with {@link PassIn} annotation. + * Passed in Element type can be declared via method type variable: prevInstance.<TypeElement>fromSourceString(...) + * + * @param className The fully qualified class name + * @param sourceString the source string of the class + * @param The type of the passed in Element + * @return the next fluent interface + */ + default UnitTestWhenWithPassedInElementAndProcessorInterface fromSourceString(String className, String sourceString) { + return this.fromJavaFileObject(JavaFileObjectUtils.readFromString(className, sourceString)); + } + + /** + * Passes in an Element via the resource path String of a source file. + * The source file must contain exactly one Element annotated with {@link PassIn} annotation. + * Passed in Element type can be declared via method type variable: prevInstance.<TypeElement>fromSourceFile(...) + * + * @param resourceName The resource path String of the source file + * @param The type of the passed in Element + * @return the next fluent interface + */ + default UnitTestWhenWithPassedInElementAndProcessorInterface fromSourceFile(String resourceName) { + return this.fromJavaFileObject(JavaFileObjectUtils.readFromResource(resourceName)); + } + + /** + * Passes in an Element via a JavaFileObject representing a source file. + * The JavaFileObject must contain exactly one Element annotated with {@link PassIn} annotation. + * Passed in Element type can be declared via method type variable: prevInstance.<TypeElement>fromJavaFileObject(...) + * + * @param javaFileObject The JavaFileObject representing a source file + * @param The type of the passed in Element + * @return the next fluent interface + */ + @FluentApiParentBackingBeanMapping(value = "passInConfiguration") + @FluentApiImplicitValue(id = "passInElement", value = "true") + UnitTestWhenWithPassedInElementAndProcessorInterface fromJavaFileObject(@FluentApiBackingBeanMapping(value = "sourceFiles", action = MappingAction.SET, target = TargetBackingBean.NEXT) @NotNull JavaFileObject javaFileObject); + + /** + * The Element will be passed in via a compiled class. + * Class must contain exactly one element annotated with {@link PassIn} annotation. + * Warning: All non-runtime annotations on the element won't be accessible!!! + * Use source file approach if you need to support non-runtime annotations. + * + * @param classToScanForElement the class to scan for Element + * @param the element type + * @return the next fluent interface + */ + + @FluentApiParentBackingBeanMapping(value = "passInConfiguration") + @FluentApiImplicitValue(id = "passInElement", value = "true") + UnitTestWhenWithPassedInElementAndProcessorInterface fromClass(@FluentApiBackingBeanMapping(value = "passedInClass", target = TargetBackingBean.THIS) @NotNull Class classToScanForElement); + + /** + * The element will be passed in from given source files. Exactly one Source file must contain a PassIn annotation. + * This method should only be used, if non-runtime annotations are involved in unit tests. + * + * @param the Element type of passed in interface. + * @return the next fluent interface + */ + @FluentApiParentBackingBeanMapping(value = "passInConfiguration") + @FluentApiImplicitValue(id = "passInElement", value = "true") + UnitTestWhenWithPassedInElementAndProcessorInterface fromGivenSourceFiles(); + + } + + + @FluentApiInterface(CompilerTestBB.class) + public interface UnitTestWhenWithPassedInElementAndProcessorInterface { + + /** + * Define unit test. + * + * @param unitTest the unit test + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "getPassInType", value = "ELEMENT_AND_PROCESSOR", target = TargetBackingBean.NEXT) + UnitTestInterface intoUnitTest(@FluentApiBackingBeanMapping(value = "unitTest", action = MappingAction.SET) @NotNull UnitTestForTestingAnnotationProcessors unitTest); + } + + + // -------------------------------------------------------------------- + // Common "then" Interfaces + // -------------------------------------------------------------------- + + @FluentApiInterface(CompilerTestBB.class) + public interface UnitTestInterface { + + /** + * Traverse to section to define checks + * + * @return the next fluent interface + */ + UnitTestOutcomeInterface thenExpectThat(); + + /** + * Executes the test. + * All AssertionError triggered inside the unit test will bepassed through to your unit test framework. + */ + @FluentApiCommand(ExecuteTestCommand.class) + void executeTest(); + + + } + + @FluentApiInterface(CompilerTestBB.class) + public interface BlackBoxTestInterface { + + /** + * Traverse to section to define checks + * + * @return the next fluent interface + */ + BlackBoxTestOutcomeInterface thenExpectThat(); + + /** + * Executes the test. + * All AssertionError triggered inside the unit test will bepassed through to your unit test framework. + */ + @FluentApiCommand(ExecuteTestCommand.class) + void executeTest(); + + + } + + + @FluentApiInterface(CompilerTestBB.class) + public interface BlackBoxTestOutcomeInterface { + + /** + * Expect tbe compilation to be successful. + * This means that all (generated) source file are compiled successfully and that no error compiler message has been written. + * + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "compilationSucceeded", value = "true") + CompilerTestExpectAndThatInterface compilationSucceeds(); + + /** + * Expect the compilation to fail. + * This means that either a (generated) source file couldn't be compiled ot that an error compiler message has been written. + * + * @return the next fluent imnterface + */ + @FluentApiImplicitValue(id = "compilationSucceeded", value = "false") + CompilerTestExpectAndThatInterface compilationFails(); + + + + } + + @FluentApiInterface(CompilerTestBB.class) + public interface UnitTestOutcomeInterface extends BlackBoxTestOutcomeInterface{ + + /** + * Expect an Exception to be thrown + * + * @param exception The exception to check for + * @return the next fluent interface + */ + CompilerTestExpectAndThatInterface exceptionIsThrown(@FluentApiBackingBeanMapping(value = "exceptionIsThrown") Class exception); + + + } + + + + @FluentApiInterface(CompilerTestBB.class) + public interface CompilerTestExpectAndThatInterface { + + /** + * Add another expectation. + * + * @return the next fluent interface + */ + CompilerTestExpectThatInterface andThat(); + + /** + * Executes the test. + */ + @FluentApiCommand(ExecuteTestCommand.class) + void executeTest(); + + } + + @FluentApiInterface(CompilerTestBB.class) + public interface CompilerTestExpectThatInterface { + + /** + * Adds check that generated class exists or doesn't exist. + * + * @param className the fully qualified class name + * @return the next fluent interface + */ + default GeneratedJavaFileObjectCheck generatedClass(String className) { + return javaFileObject(StandardLocation.CLASS_OUTPUT, className, JavaFileObject.Kind.CLASS); + } + + /** + * Adds check that generated source file exists or doesn't exist. + * + * @param className the fully qualified class name + * @return the next fluent interface + */ + default GeneratedJavaFileObjectCheck generatedSourceFile(String className) { + return javaFileObject(StandardLocation.SOURCE_OUTPUT, className, JavaFileObject.Kind.SOURCE); + } + + /** + * Adds check that generated resource file exists or doesn't exist. + * + * @param packageName the package of the resource file + * @param relativeName The relative name of the resource file + * @return the next fluent interface + */ + default GeneratedFileObjectCheck generatedResourceFile(String packageName, String relativeName) { + return fileObject(StandardLocation.CLASS_OUTPUT, packageName, relativeName); + } + + /** + * Check if a JavaFileObject exists. + * + * @param location The location of the JavaFileObject + * @param className The fully qualified name of the JavaFileObject + * @param kind The kind of the JavaFileObject + * @return the next fluent interface + */ + GeneratedJavaFileObjectCheck javaFileObject(@FluentApiBackingBeanMapping(value = "location", target = TargetBackingBean.NEXT) @NotNull JavaFileManager.Location location, @FluentApiBackingBeanMapping(value = "className", target = TargetBackingBean.NEXT) @NotNull String className, @FluentApiBackingBeanMapping(value = "kind", target = TargetBackingBean.NEXT) @NotNull JavaFileObject.Kind kind); + + /** + * Check if a FileObject exists. + * + * @param location The location of the FileObject + * @param packageName The package name of the FileObject + * @param relativeName The kind of the FileObject + * @return the next fluent interface + */ + GeneratedFileObjectCheck fileObject(@FluentApiBackingBeanMapping(value = "location", target = TargetBackingBean.NEXT) @NotNull JavaFileManager.Location location, @FluentApiBackingBeanMapping(value = "packageName", target = TargetBackingBean.NEXT) @NotNull String packageName, @FluentApiBackingBeanMapping(value = "relativeName", target = TargetBackingBean.NEXT) @NotNull String relativeName); + + + /** + * Adds compiler message checks. + * + * @return the next fluent interface + */ + CompilerMessageCheckMessageType compilerMessage(); + + + } + + + @FluentApiInterface(CompilerMessageCheckBB.class) + public interface CompilerMessageCheckMessageType { + + /** + * Expects a compiler message of kind NOTE. + * + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "compilerMessageScope", value = "NOTE") + CompilerMessageCheckComparisonType ofKindNote(); + + /** + * Expects a compiler message of kind WARNING. + * + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "compilerMessageScope", value = "WARNING") + CompilerMessageCheckComparisonType ofKindWarning(); + + /** + * Expects a compiler message of kind MANDATORY WARNING. + * + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "compilerMessageScope", value = "MANDATORY_WARNING") + CompilerMessageCheckComparisonType ofKindMandatoryWarning(); + + /** + * Expects a compiler message of kind ERROR. + * + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "compilerMessageScope", value = "ERROR") + CompilerMessageCheckComparisonType ofKindError(); + + } + + @FluentApiInterface(CompilerMessageCheckBB.class) + public interface CompilerMessageCheckComparisonType { + + /** + * Check if a compiler message contains passed snippet Strings. + * + * @param text text snippets that must be present in one compiler message + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "compilerMessageComparisonType", value = "CONTAINS") + @FluentApiParentBackingBeanMapping(value = "compileMessageChecks") + CompilerTestExpectAndThatInterface contains(@FluentApiBackingBeanMapping(value = "searchString", action = MappingAction.SET) @NotNull String... text); + + /** + * Check if a compiler message exists that equals passed String. + * + * @param text the text to check for + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "compilerMessageComparisonType", value = "EQUALS") + @FluentApiParentBackingBeanMapping(value = "compileMessageChecks") + CompilerTestExpectAndThatInterface equals(@FluentApiBackingBeanMapping(value = "searchString", action = MappingAction.SET) @NotNull String text); + + /** + * Expect compiler message at line. + * + * @param line the line number the compiler message must be located + * @return the next fluent interface + */ + CompilerMessageCheckComparisonType atLine(@FluentApiBackingBeanMapping(value = "atLine") int line); + + /** + * Expect compiler message at column. + * + * @param column the column number the compiler message must be located + * @return the next fluent interface + */ + CompilerMessageCheckComparisonType atColumn(@FluentApiBackingBeanMapping(value = "atColumn") int column); + + /** + * Expect compiler message in source file. + * + * @param atSource the source file the compiler message bound with. + * @return the next fluent interface + */ + CompilerMessageCheckComparisonType atSource(@FluentApiBackingBeanMapping(value = "atSource") String atSource); + + /** + * The locale used for compiler message. + * + * @param locale the expected locale of the compiler message + * @return the next fluent interface + */ + CompilerMessageCheckComparisonType withLocale(@FluentApiBackingBeanMapping(value = "withLocale") Locale locale); + + } + + @FluentApiInterface(GeneratedJavaFileObjectCheckBB.class) + public interface GeneratedJavaFileObjectCheck { + + /** + * Expect a file to be existent. + * + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "checkType", value = "EXISTS") + @FluentApiParentBackingBeanMapping(value = "javaFileObjectChecks", action = MappingAction.ADD) + CompilerTestExpectAndThatInterface exists(); + + /** + * Expect a file to be nonexistent. + * + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "checkType", value = "DOESNT_EXIST") + @FluentApiParentBackingBeanMapping(value = "javaFileObjectChecks", action = MappingAction.ADD) + CompilerTestExpectAndThatInterface doesntExist(); + + /** + * Expect a file to be binary equal to passed JavaFileObject. + * + * @param expectedJavaFileObject the expected file used for comparison + * @return the next fluent interface + */ + default CompilerTestExpectAndThatInterface equals(JavaFileObject expectedJavaFileObject) { + return matches(ExpectedFileObjectMatcherKind.BINARY, expectedJavaFileObject); + } + + /** + * Expect that a file matches the passed JavaFileObject and Matcher kind. + * + * @param expectedJavaFileObject the expected file used for comparison + * @return the next fluent interface + */ + default CompilerTestExpectAndThatInterface matches(ExpectedFileObjectMatcherKind expectedFileObjectMatcherKind, JavaFileObject expectedJavaFileObject) { + return matches(expectedFileObjectMatcherKind.createMatcher(expectedJavaFileObject)); + } + + /** + * Expect that a file exists that matches the passed GeneratedFileObjectMatcher. + * + * @param generatedJavaFileObjectCheck the GeneratedFileObjectMatcher to use + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "checkType", value = "EXISTS") + @FluentApiParentBackingBeanMapping(value = "javaFileObjectChecks", action = MappingAction.ADD) + CompilerTestExpectAndThatInterface matches(@FluentApiBackingBeanMapping(value = "generatedFileObjectMatcher") GeneratedFileObjectMatcher generatedJavaFileObjectCheck); + + } + + @FluentApiInterface(GeneratedFileObjectCheckBB.class) + public interface GeneratedFileObjectCheck { + + /** + * Expect the file to exist. + * + * @return The next fluent interface + */ + @FluentApiImplicitValue(id = "checkType", value = "EXISTS") + @FluentApiParentBackingBeanMapping(value = "fileObjectChecks", action = MappingAction.ADD) + CompilerTestExpectAndThatInterface exists(); + + /** + * Expect the file to be nonexistent. + * + * @return The next fluent interface + */ + @FluentApiImplicitValue(id = "checkType", value = "DOESNT_EXIST") + @FluentApiParentBackingBeanMapping(value = "fileObjectChecks", action = MappingAction.ADD) + CompilerTestExpectAndThatInterface doesntExist(); + + /** + * Expect that a file exists that matches the passed FileObject. + * Matcher ignores line endings. + * + * @param expectedFileObject the FileOject used for comparison + * @return the next fluent inmterface + */ + default CompilerTestExpectAndThatInterface equals(FileObject expectedFileObject) { + return matches(ExpectedFileObjectMatcherKind.TEXT_IGNORE_LINE_ENDINGS, expectedFileObject); + } + + /** + * Expect that a file exists that matches the passed FileObject. + * + * @param expectedFileObjectMatcherKind The matcher kind + * @param expectedFileObject the FileOject used for comparison + * @return the next fluent interface + */ + default CompilerTestExpectAndThatInterface matches(ExpectedFileObjectMatcherKind expectedFileObjectMatcherKind, FileObject expectedFileObject) { + return matches(expectedFileObjectMatcherKind.createMatcher(expectedFileObject)); + } + + /** + * Expect a file that matches all passed GeneratedFileObjectMatchers. + * + * @param generatedJavaFileObjectCheck the GeneratedFileObjectMatchers to use + * @return the next fluent interface + */ + @FluentApiImplicitValue(id = "checkType", value = "EXISTS") + @FluentApiParentBackingBeanMapping(value = "fileObjectChecks", action = MappingAction.ADD) + CompilerTestExpectAndThatInterface matches(@FluentApiBackingBeanMapping(value = "generatedFileObjectMatcher") GeneratedFileObjectMatcher... generatedJavaFileObjectCheck); + + + } + + + /** + * Configures how FileObjects should be compared. + */ + public enum ExpectedFileObjectMatcherKind { + /** + * Does binary comparison. + * Be careful: tests using binary comparison may fail because of line-endings depending on OS. + */ + BINARY { + @Override + public GeneratedFileObjectMatcher createMatcher(T expectedFileObject) { + return CoreGeneratedFileObjectMatchers.createBinaryMatcher(expectedFileObject); + } + }, + /** + * Textual comparison line by line by ignoring the OS depending line-endings. + */ + TEXT_IGNORE_LINE_ENDINGS { + @Override + public GeneratedFileObjectMatcher createMatcher(T expectedFileObject) { + return CoreGeneratedFileObjectMatchers.createIgnoreLineEndingsMatcher(expectedFileObject); + } + }; + + /** + * Creates a matcher for FileObjects for enum value. + * + * @param expectedFileObject the expected FileObject + * @param The type of FileObject + * @return a GeneratedFileObjectMatcher instance that can be used to compare FileObjects + */ + protected abstract GeneratedFileObjectMatcher createMatcher(T expectedFileObject); + } + + // -------------------------------------------------------------------- + // Commands + // -------------------------------------------------------------------- + + @FluentApiCommand + public static class ExecuteTestCommand { + static void myCommand(CompilerTestBB backingBean) { + new CompileTest(backingBean).executeTest(); + } + } + + +} \ No newline at end of file diff --git a/cute/src/main/java/io/toolisticon/cute/impl/DebugOutputGenerator.java b/cute/src/main/java/io/toolisticon/cute/DebugOutputGenerator.java similarity index 96% rename from cute/src/main/java/io/toolisticon/cute/impl/DebugOutputGenerator.java rename to cute/src/main/java/io/toolisticon/cute/DebugOutputGenerator.java index f7e4e3b..c025ee8 100644 --- a/cute/src/main/java/io/toolisticon/cute/impl/DebugOutputGenerator.java +++ b/cute/src/main/java/io/toolisticon/cute/DebugOutputGenerator.java @@ -1,6 +1,5 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; -import io.toolisticon.cute.FailingAssertionException; import io.toolisticon.cute.extension.api.ModuleSupportSpi; import io.toolisticon.cute.extension.api.ModuleSupportSpiServiceLocator; @@ -28,7 +27,7 @@ private DebugOutputGenerator() { } - static String getDebugOutput(CompilationResult compilationResult, CompileTestConfiguration compileTestConfiguration, FailingAssertionException failingAssertionException) { + static String getDebugOutput(CompilationResult compilationResult, CuteApi.CompilerTestBB compileTestConfiguration, FailingAssertionException failingAssertionException) { StringBuilder stringBuilder = new StringBuilder(); @@ -61,7 +60,7 @@ static String getDebugOutput(CompilationResult compilationResult, CompileTestCon // Compile test configuration stringBuilder.append(getDebugOutputHeader("COMPILE TEST CONFIGURATION")).append(compileTestConfiguration.toString()); - if (!Java9SupportCheck.UNSUPPORTED_JAVA_VERSION && compileTestConfiguration.getModules() != null) { + if (!Java9SupportCheck.UNSUPPORTED_JAVA_VERSION && compileTestConfiguration.modules() != null) { ModuleSupportSpi moduleSupportSpi = ModuleSupportSpiServiceLocator.locate(); if (moduleSupportSpi != null) { diff --git a/cute/src/main/java/io/toolisticon/cute/FileObjectUtils.java b/cute/src/main/java/io/toolisticon/cute/FileObjectUtils.java new file mode 100644 index 0000000..f3271d9 --- /dev/null +++ b/cute/src/main/java/io/toolisticon/cute/FileObjectUtils.java @@ -0,0 +1,281 @@ +package io.toolisticon.cute; + +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardLocation; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +/** + * Utility class to create JavaFileObjects and therefore also FileObjects. + * These files can be used for comparison or as source files during compilation. + */ +public class FileObjectUtils { + + + /** + * A file object used to represent source coming from a string. + */ + public static class JavaSourceFromString extends SimpleJavaFileObject { + /** + * The source content of this "file". + */ + private final String content; + + /** + * Constructs a new JavaSourceFromString. + * + * @param name the name of the compilation unit represented by this file object + * @param content the source content for the compilation unit represented by this file object + */ + private JavaSourceFromString(String name, String content) { + super(URI.create("string://" + StandardLocation.SOURCE_PATH + "/" + name.replace('.', '/') + Kind.SOURCE.extension), + Kind.SOURCE); + this.content = content; + } + + + @Override + public InputStream openInputStream() { + return new ByteArrayInputStream(this.content.getBytes()); + } + + @Override + public Reader openReader(boolean ignoreEncodingErrors) { + return new InputStreamReader(openInputStream()); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return content; + } + + + } + + /** + * Resource based java source. + */ + public static class JavaSourceFromResource extends SimpleJavaFileObject { + + private final static String JAVA_COMPATIBILITY_FILE_ENDING_SUFFIX = ".ct"; + + private final Class relativeLocationRoot; + private final String location; + + private JavaSourceFromResource(String location, Class relativeLocationRoot) { + + super(URI.create("resource://" + (location.endsWith(".java" + JAVA_COMPATIBILITY_FILE_ENDING_SUFFIX) ? location.substring(0, location.length() - JAVA_COMPATIBILITY_FILE_ENDING_SUFFIX.length()) : location)), Kind.SOURCE); + this.relativeLocationRoot = relativeLocationRoot; + this.location = location; + + } + + @Override + public InputStream openInputStream() { + + Class relativeRoot = relativeLocationRoot != null ? relativeLocationRoot : FileObjectUtils.class; + InputStream inputStream = relativeRoot.getResourceAsStream(location); + + if (inputStream == null) { + throw new IllegalStateException(Constants.Messages.ISE_CANNOT_OPEN_INPUTSTREAM_WITH_URI.produceMessage(uri.toString())); + } + + return inputStream; + } + + @Override + public Reader openReader(boolean ignoreEncodingErrors) { + return new InputStreamReader(openInputStream()); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return readFromInputStream(openInputStream()); + } + } + + + /** + * Url based java source. + */ + public static class JavaSourceFromUrl extends SimpleJavaFileObject { + + private final URL url; + + private JavaSourceFromUrl(URL url) throws URISyntaxException { + super(url.toURI(), Kind.SOURCE); + this.url = url; + } + + + @Override + public InputStream openInputStream() throws IOException { + return url.openStream(); + } + + @Override + public Reader openReader(boolean ignoreEncodingErrors) throws IOException { + return new InputStreamReader(openInputStream()); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return readFromInputStream(openInputStream()); + } + } + + + /** + * Read a java source file from resources. + *

+ * Some IDEs like Eclipse don't like resource files ending with *.java. + * In this case extend the file name by ".ct" suffix (f.e. "JavaClass.java.ct"). + * The suffix will be ignored for looking up files via the compile-test file manager. + * * + * + * @param location the location + * @param relativeLocationRoot relative location root class + * @return The SimpleJavaFileObject for resource + */ + public static SimpleJavaFileObject readFromResource(String location, Class relativeLocationRoot) { + + if (location == null) { + throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("location")); + } + + return new JavaSourceFromResource(location, relativeLocationRoot); + } + + /** + * Read a java source file from resources. + * Passed location will be handled as absolute path and will be used to both read resource and as location in compile test file manager. + *

+ * Some IDEs like Eclipse don't like resource files ending with *.java. + * In this case extend the file name by ".ct" suffix (f.e. "JavaClass.java.ct"). + * The suffix will be ignored for looking up files via the compile-test file manager. + * + * @param location the location + * @return The SimpleJavaFileObject for resource + */ + public static SimpleJavaFileObject readFromResource(String location) { + + if (location == null) { + throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("location")); + } + + return new JavaSourceFromResource((!location.startsWith("/") ? "/" : "") + location, null); + } + + /** + * Reads multiple java source files from resources. + * Passed locations will be handled as absolute path and will be used to both read resource and as location in compile test file manager. + *

+ * Some IDEs like Eclipse don't like resource files ending with *.java. + * In this case extend the file name by ".ct" suffix (f.e. "JavaClass.java.ct"). + * The suffix will be ignored for looking up files via the compile-test file manager. + * + * @param locations the location + * @return The SimpleJavaFileObject for resource + */ + public static SimpleJavaFileObject[] readFromResources(String... locations) { + + List resourceFiles = new ArrayList<>(); + + for (String location : locations) { + resourceFiles.add(readFromResource(location)); + } + + return resourceFiles.toArray(new SimpleJavaFileObject[0]); + } + + /** + * Read a java source file from string. + * + * @param location the location + * @param content content of the file + * @return The SimpleJavaFileObject for passed content string + */ + public static SimpleJavaFileObject readFromString(String location, String content) { + + if (location == null) { + throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("location")); + } + + if (content == null) { + throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("content")); + } + + return new JavaSourceFromString(location, content); + } + + /** + * Read a java source file from resources. + * This one works great if you don't rely on the location, f.e. in case of comparison. + * + * @param content content of the file + * @return he SimpleJavaFileObject for passed content string + */ + public static SimpleJavaFileObject readFromString(String content) { + + // create a random location + String location = "string_" + CommonUtilities.getRandomString(6); + + return readFromString(location, content); + } + + + /** + * Read a java source file from resources. + * + * @param url the location + * @return The SimpleJavaFileObject for passed URL + * @throws URISyntaxException if passed url cannot be converted into URI + * @throws IllegalArgumentException if passed url is null + */ + public static SimpleJavaFileObject readFromUrl(URL url) throws URISyntaxException { + + if (url == null) { + throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("url")); + } + + return new JavaSourceFromUrl(url); + } + + + /** + * Reads a String from an InputStream. + * CLoses the stream + * + * @param stream the inputStream to use + * @return The String read from the inputStreams + * @throws IOException if an error occurs + */ + private static String readFromInputStream(InputStream stream) throws IOException { + + byte[] buffer = new byte[10000]; + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + int line; + // read bytes from stream, and store them in buffer + while ((line = stream.read(buffer)) != -1) { + // Writes bytes from byte array (buffer) into output stream. + os.write(buffer, 0, line); + } + stream.close(); + os.flush(); + os.close(); + + return os.toString(); + } + + +} diff --git a/cute/src/main/java/io/toolisticon/cute/impl/Java9SupportCheck.java b/cute/src/main/java/io/toolisticon/cute/Java9SupportCheck.java similarity index 94% rename from cute/src/main/java/io/toolisticon/cute/impl/Java9SupportCheck.java rename to cute/src/main/java/io/toolisticon/cute/Java9SupportCheck.java index 7d908b3..4d671ca 100644 --- a/cute/src/main/java/io/toolisticon/cute/impl/Java9SupportCheck.java +++ b/cute/src/main/java/io/toolisticon/cute/Java9SupportCheck.java @@ -1,4 +1,4 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; /** * Utility class to check if java 9 api is unsupported. diff --git a/cute/src/main/java/io/toolisticon/cute/JavaFileObjectUtils.java b/cute/src/main/java/io/toolisticon/cute/JavaFileObjectUtils.java index e3e15a0..1ad135b 100644 --- a/cute/src/main/java/io/toolisticon/cute/JavaFileObjectUtils.java +++ b/cute/src/main/java/io/toolisticon/cute/JavaFileObjectUtils.java @@ -1,7 +1,5 @@ package io.toolisticon.cute; -import io.toolisticon.cute.impl.CommonUtilities; - import javax.tools.SimpleJavaFileObject; import javax.tools.StandardLocation; import java.io.ByteArrayInputStream; diff --git a/cute/src/main/java/io/toolisticon/cute/UnitTest.java b/cute/src/main/java/io/toolisticon/cute/UnitTest.java index 70a4cea..46607c0 100644 --- a/cute/src/main/java/io/toolisticon/cute/UnitTest.java +++ b/cute/src/main/java/io/toolisticon/cute/UnitTest.java @@ -11,7 +11,7 @@ *

* Please use {@link UnitTestForTestingAnnotationProcessors} if you want to unit test annotation processor methods. */ -public interface UnitTest { +public interface UnitTest extends UnitTestBase { /** * The unit test method. diff --git a/cute/src/main/java/io/toolisticon/cute/UnitTestAnnotationProcessorClassForTestingAnnotationProcessorsWithoutPassIn.java b/cute/src/main/java/io/toolisticon/cute/UnitTestAnnotationProcessorClassForTestingAnnotationProcessorsWithoutPassIn.java new file mode 100644 index 0000000..04104a1 --- /dev/null +++ b/cute/src/main/java/io/toolisticon/cute/UnitTestAnnotationProcessorClassForTestingAnnotationProcessorsWithoutPassIn.java @@ -0,0 +1,62 @@ +package io.toolisticon.cute; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.TypeElement; +import java.lang.annotation.Annotation; +import java.util.Set; + +/** + * Base annotation processor for unit testing of initialized annotation processors. + * + * @param the unit test processor to use + */ +class UnitTestAnnotationProcessorClassForTestingAnnotationProcessorsWithoutPassIn extends AbstractUnitTestAnnotationProcessorClass { + + + /** + * The unit test processor instance to use. + */ + private final UnitTestForTestingAnnotationProcessorsWithoutPassIn unitTestForTestingAnnotationProcessors; + private final UNIT_PROCESSOR processorUnderTest; + + + public UnitTestAnnotationProcessorClassForTestingAnnotationProcessorsWithoutPassIn(UNIT_PROCESSOR processorUnderTest, Class annotationTypeToUse, UnitTestForTestingAnnotationProcessorsWithoutPassIn unitTestForTestingAnnotationProcessors) { + super(annotationTypeToUse); + this.processorUnderTest = processorUnderTest; + this.unitTestForTestingAnnotationProcessors = unitTestForTestingAnnotationProcessors; + } + + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + + // call init method of annotation processor under test + processorUnderTest.init(processingEnv); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + + // just try to execute tests if annotation is processed == annotations size is 1 + if (!roundEnv.processingOver() && annotations.size() == 1) { + + try { + unitTestForTestingAnnotationProcessors.unitTest(processorUnderTest, this.processingEnv); + } catch (ClassCastException e) { + if (e.getMessage() != null && e.getMessage().contains("com.sun.tools.javac.code.Symbol$ClassSymbol")) { + throw new FailingAssertionException(Constants.Messages.UNIT_TEST_PRECONDITION_INCOMPATIBLE_ELEMENT_TYPE.produceMessage()); + } else { + throw e; + } + } + + + } + + return false; + } + + +} diff --git a/cute/src/main/java/io/toolisticon/cute/UnitTestAnnotationProcessorClassWithPassIn.java b/cute/src/main/java/io/toolisticon/cute/UnitTestAnnotationProcessorClassWithPassIn.java index d994e6b..9fda934 100644 --- a/cute/src/main/java/io/toolisticon/cute/UnitTestAnnotationProcessorClassWithPassIn.java +++ b/cute/src/main/java/io/toolisticon/cute/UnitTestAnnotationProcessorClassWithPassIn.java @@ -6,7 +6,7 @@ import java.lang.annotation.Annotation; import java.util.Set; -public class UnitTestAnnotationProcessorClassWithPassIn extends AbstractUnitTestAnnotationProcessorWithPassIn { +class UnitTestAnnotationProcessorClassWithPassIn extends AbstractUnitTestAnnotationProcessorWithPassIn { /** diff --git a/cute/src/main/java/io/toolisticon/cute/UnitTestAnnotationProcessorClassWithoutPassIn.java b/cute/src/main/java/io/toolisticon/cute/UnitTestAnnotationProcessorClassWithoutPassIn.java new file mode 100644 index 0000000..edaa2c2 --- /dev/null +++ b/cute/src/main/java/io/toolisticon/cute/UnitTestAnnotationProcessorClassWithoutPassIn.java @@ -0,0 +1,52 @@ +package io.toolisticon.cute; + +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import java.lang.annotation.Annotation; +import java.util.Set; + +/** + * Base annotation processor for unit tests. + * + */ +class UnitTestAnnotationProcessorClassWithoutPassIn extends AbstractUnitTestAnnotationProcessorClass { + + /** + * The unit test processor instance to use. + */ + private final UnitTestWithoutPassIn unitTest; + + + public UnitTestAnnotationProcessorClassWithoutPassIn(Class annotationTypeToUse, UnitTestWithoutPassIn unitTest) { + super(annotationTypeToUse); + + this.unitTest = unitTest; + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + + // just try to execute tests if annotation is processed == annotations size is 1 + if (!roundEnv.processingOver() && annotations.size() == 1) { + Set set = roundEnv.getElementsAnnotatedWith(annotationTypeToUse); + + + try { + unitTest.unitTest(this.processingEnv); + } catch (ClassCastException e) { + if (e.getMessage() != null && e.getMessage().contains("com.sun.tools.javac.code.Symbol$ClassSymbol")) { + throw new FailingAssertionException(Constants.Messages.UNIT_TEST_PRECONDITION_INCOMPATIBLE_ELEMENT_TYPE.produceMessage()); + } else { + throw e; + } + } + + } + return false; + } + +} + + + diff --git a/cute/src/main/java/io/toolisticon/cute/UnitTestBase.java b/cute/src/main/java/io/toolisticon/cute/UnitTestBase.java new file mode 100644 index 0000000..f3c42e4 --- /dev/null +++ b/cute/src/main/java/io/toolisticon/cute/UnitTestBase.java @@ -0,0 +1,8 @@ +package io.toolisticon.cute; + +/** + * Base interface used to store unit tests in backing bean. + * Will be later handled via instanceof. + */ +public interface UnitTestBase { +} diff --git a/cute/src/main/java/io/toolisticon/cute/UnitTestForTestingAnnotationProcessors.java b/cute/src/main/java/io/toolisticon/cute/UnitTestForTestingAnnotationProcessors.java index cbf8165..01d1f17 100644 --- a/cute/src/main/java/io/toolisticon/cute/UnitTestForTestingAnnotationProcessors.java +++ b/cute/src/main/java/io/toolisticon/cute/UnitTestForTestingAnnotationProcessors.java @@ -11,7 +11,7 @@ * @param the processor to use * @param the expected element type to be found */ -public interface UnitTestForTestingAnnotationProcessors { +public interface UnitTestForTestingAnnotationProcessors extends UnitTestBase { /** * The unit test method. diff --git a/cute/src/main/java/io/toolisticon/cute/UnitTestForTestingAnnotationProcessorsWithoutPassIn.java b/cute/src/main/java/io/toolisticon/cute/UnitTestForTestingAnnotationProcessorsWithoutPassIn.java new file mode 100644 index 0000000..4525eea --- /dev/null +++ b/cute/src/main/java/io/toolisticon/cute/UnitTestForTestingAnnotationProcessorsWithoutPassIn.java @@ -0,0 +1,22 @@ +package io.toolisticon.cute; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.Processor; + +/** + * Interface that is used during unit test creation. It allows setting up a unit test without the need to create a valid annotation processor. + * In comparison to {@link UnitTest} an instance of the processor under test will be created and it's init method will be called. + * + * @param the processor to use + */ +public interface UnitTestForTestingAnnotationProcessorsWithoutPassIn extends UnitTestBase { + + /** + * The unit test method. + * + * @param unit the initialized processor under test (initialized via init method) + * @param processingEnvironment the processingEnvironment + */ + void unitTest(PROCESSOR unit, ProcessingEnvironment processingEnvironment); +} + diff --git a/cute/src/main/java/io/toolisticon/cute/UnitTestWithoutPassIn.java b/cute/src/main/java/io/toolisticon/cute/UnitTestWithoutPassIn.java new file mode 100644 index 0000000..bb98c3b --- /dev/null +++ b/cute/src/main/java/io/toolisticon/cute/UnitTestWithoutPassIn.java @@ -0,0 +1,19 @@ +package io.toolisticon.cute; + +import javax.annotation.processing.ProcessingEnvironment; + +/** + * Interface that is used during unit test creation. It allows setting up a unit test without the need to create a valid annotation processor. + *

*

+ * Please use {@link UnitTestForTestingAnnotationProcessors} if you want to unit test annotation processor methods. + */ +public interface UnitTestWithoutPassIn extends UnitTestBase{ + + /** + * The unit test method. + * + * @param processingEnvironment the processingEnvironment + */ + void unitTest(ProcessingEnvironment processingEnvironment); + +} diff --git a/cute/src/main/java/io/toolisticon/cute/impl/AnnotationProcessorWrapper.java b/cute/src/main/java/io/toolisticon/cute/impl/AnnotationProcessorWrapper.java deleted file mode 100644 index 647c932..0000000 --- a/cute/src/main/java/io/toolisticon/cute/impl/AnnotationProcessorWrapper.java +++ /dev/null @@ -1,180 +0,0 @@ -package io.toolisticon.cute.impl; - -import io.toolisticon.cute.Constants; -import io.toolisticon.cute.FailingAssertionException; - -import javax.annotation.processing.Completion; -import javax.annotation.processing.Messager; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.Processor; -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; -import java.util.Set; - -/** - * Wrapper class for {@link Processor}. Allows generic creation of generic unit tests. - */ -final class AnnotationProcessorWrapper implements Processor { - - private final Processor wrappedProcessor; - private final Class expectedThrownException; - private Messager messager; - - private boolean firstRound = true; - private boolean expectedExceptionWasThrown = false; - - private AnnotationProcessorWrapper(Processor processor) { - this(processor, null); - } - - private AnnotationProcessorWrapper(Processor processor, Class expectedThrownException) { - this.wrappedProcessor = processor; - this.expectedThrownException = expectedThrownException; - } - - - @Override - public Set getSupportedOptions() { - return wrappedProcessor.getSupportedOptions(); - } - - @Override - public Set getSupportedAnnotationTypes() { - return wrappedProcessor.getSupportedAnnotationTypes(); - } - - @Override - public SourceVersion getSupportedSourceVersion() { - return wrappedProcessor.getSupportedSourceVersion(); - } - - @Override - public void init(ProcessingEnvironment processingEnv) { - - // get messager - messager = processingEnv.getMessager(); - - wrappedProcessor.init(processingEnv); - } - - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - - if (firstRound) { - // now set note message before calling the processor - messager.printMessage(Diagnostic.Kind.NOTE, getProcessorWasAppliedMessage()); - firstRound = false; - } - - boolean returnValue; - - try { - - returnValue = wrappedProcessor.process(annotations, roundEnv); - - } catch (Throwable e) { - - // pass through assertions - if (AssertionError.class.isAssignableFrom(e.getClass())) { - throw (AssertionError) e; - } - - if (this.expectedThrownException != null) { - - if (!this.expectedThrownException.isAssignableFrom(e.getClass())) { - throw new FailingAssertionException( - Constants.Messages.ASSERTION_GOT_UNEXPECTED_EXCEPTION_INSTEAD_OF_EXPECTED.produceMessage( - this.expectedThrownException.getCanonicalName(), - e.getClass().getCanonicalName(), - e.getMessage() != null ? Constants.Messages.TOKEN__WITH_MESSAGE + e.getMessage() : "") - , e); - } - - } else { - - // Got unexpected exception - throw new FailingAssertionException( - Constants.Messages.ASSERTION_GOT_UNEXPECTED_EXCEPTION.produceMessage( - e.getClass().getCanonicalName(), - e.getMessage() != null ? Constants.Messages.TOKEN__WITH_MESSAGE + e.getMessage() : ""), e); - - } - - return true; - - } - - // check in last round if expected exception has been thrown - if (roundEnv.processingOver() && expectedExceptionWasThrown && this.expectedThrownException != null) { - throw new FailingAssertionException( - Constants.Messages.ASSERTION_EXPECTED_EXCEPTION_NOT_THROWN.produceMessage(this.expectedThrownException.getCanonicalName()) - ); - } - - return returnValue; - } - - @Override - public Iterable getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) { - return wrappedProcessor.getCompletions(element, annotation, member, userText); - } - - public String getProcessorWasAppliedMessage() { - return CompileTestUtilities.getAnnotationProcessorWasAppliedMessage(wrappedProcessor); - } - - public Processor getWrappedProcessor() { - return wrappedProcessor; - } - - public static AnnotationProcessorWrapper wrapProcessor(Processor processorToWrap) { - return wrapProcessor(processorToWrap, null); - } - - public static AnnotationProcessorWrapper wrapProcessor(Processor processorToWrap, Class expectedThrownException) { - - if (processorToWrap == null) { - throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("processor")); - } - - return new AnnotationProcessorWrapper(processorToWrap, expectedThrownException); - } - - public static AnnotationProcessorWrapper wrapProcessor(Class processorTypeToWrap) { - if (processorTypeToWrap == null) { - throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("type")); - } - - try { - return new AnnotationProcessorWrapper(processorTypeToWrap.getDeclaredConstructor().newInstance()); - } catch (Exception e) { - throw new IllegalArgumentException(Constants.Messages.IAE_CANNOT_INSTANTIATE_PROCESSOR.produceMessage(processorTypeToWrap.getCanonicalName()), e); - } - - } - - public static AnnotationProcessorWrapper wrapProcessor(Class processorTypeToWrap, Class expectedThrownException) { - - if (processorTypeToWrap == null) { - throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("type")); - } - - if (expectedThrownException == null) { - throw new IllegalArgumentException(Constants.Messages.IAE_PASSED_PARAMETER_MUST_NOT_BE_NULL.produceMessage("expected exception")); - } - - try { - return new AnnotationProcessorWrapper(processorTypeToWrap.getDeclaredConstructor().newInstance(), expectedThrownException); - } catch (Exception e) { - throw new IllegalArgumentException(Constants.Messages.IAE_CANNOT_INSTANTIATE_PROCESSOR.produceMessage(processorTypeToWrap.getCanonicalName()), e); - } - - } - - -} diff --git a/cute/src/main/java/io/toolisticon/cute/impl/CompileTestConfiguration.java b/cute/src/main/java/io/toolisticon/cute/impl/CompileTestConfiguration.java deleted file mode 100644 index f20d469..0000000 --- a/cute/src/main/java/io/toolisticon/cute/impl/CompileTestConfiguration.java +++ /dev/null @@ -1,922 +0,0 @@ -package io.toolisticon.cute.impl; - -import io.toolisticon.cute.GeneratedFileObjectMatcher; - -import javax.annotation.processing.Processor; -import javax.tools.Diagnostic; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject; -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -/** - * The compile-test configuration to use for compilation test. - */ -public class CompileTestConfiguration { - - /** - * Allows to define a processor and add a check if exception is thrown by this processor. - */ - public static class ProcessorWithExpectedException { - - private final Class processorType; - private final Class throwable; - - public ProcessorWithExpectedException(Class processorType, Class throwable) { - this.processorType = processorType; - this.throwable = throwable; - } - - public Class getProcessorType() { - return processorType; - } - - public Class getThrowable() { - return throwable; - } - - @Override - public int hashCode() { - return (processorType != null ? processorType.hashCode() : 0) - + (throwable != null ? throwable.hashCode() : 0); - } - - @Override - public boolean equals(Object obj) { - - if (obj != null && ProcessorWithExpectedException.class.isAssignableFrom(obj.getClass())) { - - ProcessorWithExpectedException otherObj = (ProcessorWithExpectedException) obj; - - // compare processorType - if ((this.getProcessorType() == null && otherObj.getProcessorType() != null) - || (this.getProcessorType() != null && otherObj.getProcessorType() == null)) { - - return false; - - } else if ((this.getProcessorType() != null && otherObj.getProcessorType() != null)) { - if (!this.getProcessorType().equals(otherObj.getProcessorType())) { - return false; - } - } - - // compare throwable - if ((this.getThrowable() == null && otherObj.getThrowable() != null) - || (this.getThrowable() != null && otherObj.getThrowable() == null)) { - - return false; - - } else if ((this.getThrowable() != null && otherObj.getThrowable() != null)) { - if (!this.getThrowable().equals(otherObj.getThrowable())) { - return false; - } - } - - return true; - } - - return false; - } - - @Override - public String toString() { - return "ProcessorWithExpectedException{" + - "\n\t\tprocessorType=" + processorType + - ",\n\t\t throwable=" + throwable + - "\n\t" + - '}'; - } - } - - public enum ComparisonKind { - EQUALS, - CONTAINS - } - - public static class CompilerMessageCheck { - - private final Diagnostic.Kind kind; - private final ComparisonKind comparisonKind; - private final String expectedMessage; - private final Locale locale; - private final String source; - private final Long row; - private final Long column; - - - public CompilerMessageCheck(Diagnostic.Kind kind, ComparisonKind comparisonKind, String expectedMessage, Locale locale, String source, Long row, Long column) { - this.kind = kind; - this.comparisonKind = comparisonKind; - this.expectedMessage = expectedMessage; - this.locale = locale; - this.source = source; - this.row = row; - this.column = column; - } - - public Diagnostic.Kind getKind() { - return kind; - } - - public ComparisonKind getComparisonKind() { - return comparisonKind; - } - - public String getExpectedMessage() { - return expectedMessage; - } - - - public Locale getLocale() { - return locale; - } - - public String getSource() { - return source; - } - - public Long getLineNumber() { - return row; - } - - public Long getColumnNumber() { - return column; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - CompilerMessageCheck that = (CompilerMessageCheck) o; - - if (kind != that.kind) return false; - if (!Objects.equals(comparisonKind, that.comparisonKind)) - return false; - if (!Objects.equals(expectedMessage, that.expectedMessage)) - return false; - if (!Objects.equals(locale, that.locale)) return false; - if (!Objects.equals(source, that.source)) return false; - if (!Objects.equals(row, that.row)) return false; - return Objects.equals(column, that.column); - } - - @Override - public int hashCode() { - int result = kind != null ? kind.hashCode() : 0; - result = 31 * result + (comparisonKind != null ? comparisonKind.hashCode() : 0); - result = 31 * result + (expectedMessage != null ? expectedMessage.hashCode() : 0); - result = 31 * result + (locale != null ? locale.hashCode() : 0); - result = 31 * result + (source != null ? source.hashCode() : 0); - result = 31 * result + (row != null ? row.hashCode() : 0); - result = 31 * result + (column != null ? column.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "CompilerMessageCheck{" + - "kind=" + kind + - ", comparisonKind=" + comparisonKind + - ", expectedMessage='" + expectedMessage + '\'' + - ", locale=" + locale + - ", source='" + source + '\'' + - ", row=" + row + - ", column=" + column + - '}'; - } - } - - public enum FileObjectCheckType { - EXISTS, - DOESNT_EXIST - } - - public static class GeneratedJavaFileObjectCheck { - - private final FileObjectCheckType checkType; - private final JavaFileManager.Location location; - private final String className; - private final JavaFileObject.Kind kind; - - private final GeneratedFileObjectMatcher generatedFileObjectMatcher; - - public GeneratedJavaFileObjectCheck(FileObjectCheckType checkType, JavaFileManager.Location location, String className, JavaFileObject.Kind kind, GeneratedFileObjectMatcher generatedFileObjectMatcher) { - - this.checkType = checkType; - this.location = location; - this.className = className; - this.kind = kind; - - this.generatedFileObjectMatcher = generatedFileObjectMatcher; - - } - - public FileObjectCheckType getCheckType() { - return checkType; - } - - public JavaFileManager.Location getLocation() { - return location; - } - - public String getClassName() { - return className; - } - - public JavaFileObject.Kind getKind() { - return kind; - } - - - public GeneratedFileObjectMatcher getGeneratedFileObjectMatcher() { - return generatedFileObjectMatcher; - } - - @Override - public int hashCode() { - return (checkType != null ? checkType.hashCode() : 0) - + (location != null ? location.hashCode() : 0) - + (className != null ? className.hashCode() : 0) - + (kind != null ? kind.hashCode() : 0) - + (generatedFileObjectMatcher != null ? generatedFileObjectMatcher.hashCode() : 0); - } - - @Override - public boolean equals(Object obj) { - - if (obj != null && GeneratedJavaFileObjectCheck.class.isAssignableFrom(obj.getClass())) { - - GeneratedJavaFileObjectCheck otherObj = (GeneratedJavaFileObjectCheck) obj; - - // compare checkType - if ((this.getCheckType() == null && otherObj.getCheckType() != null) - || (this.getCheckType() != null && otherObj.getCheckType() == null)) { - - return false; - - } else if ((this.getCheckType() != null && otherObj.getCheckType() != null)) { - if (!this.getCheckType().equals(otherObj.getCheckType())) { - return false; - } - } - - // compare location - if ((this.getLocation() == null && otherObj.getLocation() != null) - || (this.getLocation() != null && otherObj.getLocation() == null)) { - - return false; - - } else if ((this.getLocation() != null && otherObj.getLocation() != null)) { - if (!this.getLocation().equals(otherObj.getLocation())) { - return false; - } - } - - // compare className - if ((this.getClassName() == null && otherObj.getClassName() != null) - || (this.getClassName() != null && otherObj.getClassName() == null)) { - - return false; - - } else if ((this.getClassName() != null && otherObj.getClassName() != null)) { - if (!this.getClassName().equals(otherObj.getClassName())) { - return false; - } - } - - // compare kind - if ((this.getKind() == null && otherObj.getKind() != null) - || (this.getKind() != null && otherObj.getKind() == null)) { - - return false; - - } else if ((this.getKind() != null && otherObj.getKind() != null)) { - if (!this.getKind().equals(otherObj.getKind())) { - return false; - } - } - - // compare generatedFileObjectMatchers - if ((this.getGeneratedFileObjectMatcher() == null && otherObj.getGeneratedFileObjectMatcher() != null) - || (this.getGeneratedFileObjectMatcher() != null && otherObj.getGeneratedFileObjectMatcher() == null)) { - - return false; - - } else if ((this.getGeneratedFileObjectMatcher() != null && otherObj.getGeneratedFileObjectMatcher() != null)) { - if (!this.getGeneratedFileObjectMatcher().equals(otherObj.getGeneratedFileObjectMatcher())) { - return false; - } - } - - return true; - } - - return false; - } - - - @Override - public String toString() { - return "GeneratedJavaFileObjectCheck{" + - "\n\t\tcheckType=" + checkType.name() + - ",\n\t\tlocation=" + location + - ",\n\t\t className='" + className + '\'' + - ",\n\t\t kind=" + kind + - ",\n\t\t generatedFileObjectMatchers=" + generatedFileObjectMatcher + - "\n\t" + - '}'; - } - } - - - public static class GeneratedFileObjectCheck { - - private final FileObjectCheckType checkType; - private final JavaFileManager.Location location; - private final String packageName; - private final String relativeName; - - private final GeneratedFileObjectMatcher[] generatedFileObjectMatchers; - - public GeneratedFileObjectCheck(FileObjectCheckType checkType, JavaFileManager.Location location, String packageName, String relativeName, GeneratedFileObjectMatcher[] generatedFileObjectMatchers) { - - this.checkType = checkType; - this.location = location; - this.packageName = packageName; - this.relativeName = relativeName; - - this.generatedFileObjectMatchers = generatedFileObjectMatchers; - - } - - - public FileObjectCheckType getCheckType() { - return checkType; - } - - public JavaFileManager.Location getLocation() { - return location; - } - - public String getPackageName() { - return packageName; - } - - public String getRelativeName() { - return relativeName; - } - - public GeneratedFileObjectMatcher[] getGeneratedFileObjectMatchers() { - return generatedFileObjectMatchers; - } - - @Override - public int hashCode() { - - int generatedFileObjectsMatcherHashCode = 0; - if (generatedFileObjectMatchers != null) { - for (GeneratedFileObjectMatcher gfo : generatedFileObjectMatchers) { - if (gfo != null) { - generatedFileObjectsMatcherHashCode += gfo.hashCode(); - } - } - } - - return (checkType != null ? checkType.hashCode() : 0) - + (location != null ? location.hashCode() : 0) - + (packageName != null ? packageName.hashCode() : 0) - + (relativeName != null ? relativeName.hashCode() : 0) - + generatedFileObjectsMatcherHashCode; - } - - @Override - public boolean equals(Object obj) { - - if (obj != null && GeneratedFileObjectCheck.class.isAssignableFrom(obj.getClass())) { - - GeneratedFileObjectCheck otherObj = (GeneratedFileObjectCheck) obj; - - // compare checkType - if ((this.getCheckType() == null && otherObj.getCheckType() != null) - || (this.getCheckType() != null && otherObj.getCheckType() == null)) { - - return false; - - } else if ((this.getCheckType() != null && otherObj.getCheckType() != null)) { - if (!this.getCheckType().equals(otherObj.getCheckType())) { - return false; - } - } - - // compare location - if ((this.getLocation() == null && otherObj.getLocation() != null) - || (this.getLocation() != null && otherObj.getLocation() == null)) { - - return false; - - } else if ((this.getLocation() != null && otherObj.getLocation() != null)) { - if (!this.getLocation().equals(otherObj.getLocation())) { - return false; - } - } - - // compare packageName - if ((this.getPackageName() == null && otherObj.getPackageName() != null) - || (this.getPackageName() != null && otherObj.getPackageName() == null)) { - - return false; - - } else if ((this.getPackageName() != null && otherObj.getPackageName() != null)) { - if (!this.getPackageName().equals(otherObj.getPackageName())) { - return false; - } - } - - // compare relativeName - if ((this.getRelativeName() == null && otherObj.getRelativeName() != null) - || (this.getRelativeName() != null && otherObj.getRelativeName() == null)) { - - return false; - - } else if ((this.getRelativeName() != null && otherObj.getRelativeName() != null)) { - if (!this.getRelativeName().equals(otherObj.getRelativeName())) { - return false; - } - } - - // compare generatedFileObjectMatchers - if ((this.getGeneratedFileObjectMatchers() == null && otherObj.getGeneratedFileObjectMatchers() != null) - || (this.getGeneratedFileObjectMatchers() != null && otherObj.getGeneratedFileObjectMatchers() == null)) { - - return false; - - } else if ((this.getGeneratedFileObjectMatchers() != null && otherObj.getGeneratedFileObjectMatchers() != null)) { - - - if (this.getGeneratedFileObjectMatchers().length != otherObj.getGeneratedFileObjectMatchers().length) { - return false; - } - - for (int i = 0; i < this.getGeneratedFileObjectMatchers().length; i++) { - if (!this.getGeneratedFileObjectMatchers()[i].equals(otherObj.getGeneratedFileObjectMatchers()[i])) { - return false; - } - } - - } - - return true; - } - - return false; - } - - @Override - public String toString() { - return "GeneratedFileObjectCheck{" + - "\n\t\tcheckType=" + checkType.name() + - ",\n\t\tlocation=" + location + - ",\n\t\t packageName='" + packageName + '\'' + - ",\n\t\t relativeName='" + relativeName + '\'' + - ",\n\t\t generatedFileObjectMatchers=" + generatedFileObjectMatchers + - "\n\t" + - '}'; - } - } - - public static class PassInConfiguration { - private final Class passedInClass; - private final Class annotationToScanFor; - - public PassInConfiguration(Class passedInClass, Class annotationToScanFor) { - this.passedInClass = passedInClass; - this.annotationToScanFor = annotationToScanFor; - } - - public Class getPassedInClass() { - return passedInClass; - } - - public Class getAnnotationToScanFor() { - return annotationToScanFor; - } - - @Override - public String toString() { - return "PassInConfiguration{" + - "passedInClass=" + passedInClass + - ", annotationToScanFor=" + annotationToScanFor + - '}'; - } - } - - /** - * The compiler options to use. - */ - private final List compilerOptions = new ArrayList<>(); - - /** - * The source files to use. - */ - private final Set sourceFiles = new LinkedHashSet<>(); - - /** - * The processors to use. - */ - private final Set processors = new HashSet<>(); - - /** - * The processor types to use. - */ - private final Set> processorTypes = new HashSet<>(); - - /** - * The processors to use with an expected exception raised by this specific processor. - */ - private final Set processorsWithExpectedExceptions = new HashSet<>(); - - /** - * This is a cache for all wrapped processors and must be reset after processors are added. - */ - private Set wrappedProcessors = null; - - /** - * Global processor independent expected exceptions. - */ - private Class expectedThrownException = null; - - /** - * Modules used in Java >= 9 environments - */ - private Set modules = null; - - /** - * Compilation succeeded or not - */ - private Boolean compilationShouldSucceed; - - /** - * The pass in configuration for unit tests. - */ - private PassInConfiguration passInConfiguration; - - /** - * Compiler Message checks. - */ - private final Set compilerMessageChecks = new HashSet<>(); - - - /** - * Checks for generated JavaFileObjects. - */ - private final Set generatedJavaFileObjectChecks = new HashSet<>(); - /** - * Checks for generated FileObjects. - */ - private final Set generatedFileObjectChecks = new HashSet<>(); - - /** - * Noarg constructor. - */ - public CompileTestConfiguration() { - - } - - /** - * Clone constructor. - * - * @param source the source configuration to clone froms - */ - CompileTestConfiguration(CompileTestConfiguration source) { - - this.compilerOptions.addAll(source.getCompilerOptions()); - this.sourceFiles.addAll(source.getSourceFiles()); - this.processors.addAll(source.getProcessors()); - this.processorTypes.addAll(source.getProcessorTypes()); - this.processorsWithExpectedExceptions.addAll(source.processorsWithExpectedExceptions); - this.expectedThrownException = source.getExpectedThrownException(); - - if (source.getModules() != null) { - this.modules = new HashSet<>(); - this.modules.addAll(source.getModules()); - } else { - this.modules = null; - } - - this.compilationShouldSucceed = source.getCompilationShouldSucceed(); - this.compilerMessageChecks.addAll(source.getCompilerMessageChecks()); - - this.generatedJavaFileObjectChecks.addAll(source.getGeneratedJavaFileObjectChecks()); - this.generatedFileObjectChecks.addAll(source.getGeneratedFileObjectChecks()); - - this.passInConfiguration = source.passInConfiguration; - - } - - - public Boolean getCompilationShouldSucceed() { - return compilationShouldSucceed; - } - - public void setCompilationShouldSucceed(Boolean compilationShouldSucceed) { - this.compilationShouldSucceed = compilationShouldSucceed; - } - - public void addCompilerOptions(String... compilerOptions) { - if (compilerOptions != null) { - this.compilerOptions.addAll(Arrays.asList(compilerOptions)); - } - } - - public void clearCompilerOptions() { - this.compilerOptions.clear(); - } - - - public void addSourceFiles(JavaFileObject... sourceFiles) { - if (sourceFiles != null) { - this.sourceFiles.addAll(Arrays.asList(sourceFiles)); - this.sourceFiles.remove(null); - } - } - - public void clearSourceFiles() { - this.sourceFiles.clear(); - } - - /** - * This method should only be used for unit compile tests. - * Sharing instance between test runs can cause nondeterministic behavior. - * - * @param processors the processors to use - */ - public void addProcessors(Processor... processors) { - - // reset cache - this.wrappedProcessors = null; - - if (processors != null) { - this.processors.addAll(Arrays.asList(processors)); - this.processors.remove(null); - } - } - - @SafeVarargs - public final void addProcessorTypes(Class... processorTypes) { - - // reset cache - this.wrappedProcessors = null; - - if (processorTypes != null) { - this.processorTypes.addAll(Arrays.asList(processorTypes)); - this.processorTypes.remove(null); - } - } - - public void addProcessorWithExpectedException(Class processorType, Class e) { - - // reset cache - this.wrappedProcessors = null; - - this.processorsWithExpectedExceptions.add(new ProcessorWithExpectedException(processorType, e)); - - } - - - public void addModules(String... modules) { - if (modules != null) { - if (this.modules == null) { - this.modules = new HashSet<>(); - } - this.modules.addAll(Arrays.asList(modules)); - this.modules.remove(null); - } else { - this.modules = null; - } - } - - public void clearModules() { - this.modules = null; - } - - public void addWarningMessageCheck(ComparisonKind comparisonKind, String... messages) { - addCompilerMessage(Diagnostic.Kind.WARNING, comparisonKind, messages); - } - - public void addMandatoryWarningMessageCheck(ComparisonKind comparisonKind, String... messages) { - addCompilerMessage(Diagnostic.Kind.MANDATORY_WARNING, comparisonKind, messages); - } - - public void addErrorMessageCheck(ComparisonKind comparisonKind, String... messages) { - addCompilerMessage(Diagnostic.Kind.ERROR, comparisonKind, messages); - } - - public void addNoteMessageCheck(ComparisonKind comparisonKind, String... messages) { - addCompilerMessage(Diagnostic.Kind.NOTE, comparisonKind, messages); - } - - private void addCompilerMessage(Diagnostic.Kind kind, ComparisonKind comparisonKind, String... messages) { - if (messages != null) { - for (String message : messages) { - if (message != null) { - this.compilerMessageChecks.add(new CompilerMessageCheck(kind, comparisonKind, message, null, null, null, null)); - } - } - } - } - - public void addCompilerMessageCheck(CompilerMessageCheck compilerMessageCheck) { - this.compilerMessageChecks.add(compilerMessageCheck); - } - - public void addGeneratedJavaFileObjectCheck(FileObjectCheckType checkType, JavaFileManager.Location location, String className, JavaFileObject.Kind kind, GeneratedFileObjectMatcher generatedFileObjectMatcher) { - this.generatedJavaFileObjectChecks.add(new GeneratedJavaFileObjectCheck(checkType, location, className, kind, generatedFileObjectMatcher)); - } - - public void addGeneratedJavaFileObjectCheck(FileObjectCheckType checkType, JavaFileManager.Location location, String className, JavaFileObject.Kind kind) { - this.generatedJavaFileObjectChecks.add(new GeneratedJavaFileObjectCheck(checkType, location, className, kind, null)); - } - - public final void addGeneratedFileObjectCheck(FileObjectCheckType checkType, JavaFileManager.Location location, String packageName, String relativeName, GeneratedFileObjectMatcher... generatedFileObjectMatcher) { - this.generatedFileObjectChecks.add(new GeneratedFileObjectCheck(checkType, location, packageName, relativeName, generatedFileObjectMatcher)); - } - - public void setExpectedThrownException(Class expectedThrownException) { - this.expectedThrownException = expectedThrownException; - } - - public void setPassInConfiguration(Class passedInClass, Class annotationToScanFor) { - this.passInConfiguration = passedInClass == null ? null : new PassInConfiguration(passedInClass, annotationToScanFor); - } - - public List getCompilerOptions() { - return compilerOptions; - } - - public List getNormalizedCompilerOptions() { - - List normalizedCompilerOptions = new ArrayList<>(); - - for (String compilerOption : getCompilerOptions()) { - - if (compilerOption != null) { - for (String tokenizedCompilerOption : compilerOption.split("[ ]+")) { - if (!tokenizedCompilerOption.isEmpty()) { - normalizedCompilerOptions.add(tokenizedCompilerOption); - } - } - } - } - - return normalizedCompilerOptions; - - } - - public Set getSourceFiles() { - return sourceFiles; - } - - public Set getProcessors() { - return processors; - } - - public Set> getProcessorTypes() { - return processorTypes; - } - - public Set getProcessorsWithExpectedExceptions() { - return processorsWithExpectedExceptions; - } - - - public Set getWrappedProcessors() { - - // return cached wrapped processors if available - if (wrappedProcessors != null) { - return wrappedProcessors; - } - - - Set wrappedProcessors = new HashSet<>(); - - for (Processor processor : this.processors) { - - wrappedProcessors.add(AnnotationProcessorWrapper.wrapProcessor(processor, expectedThrownException)); - - } - - for (Class processorType : this.processorTypes) { - - try { - Processor processor = processorType.getDeclaredConstructor().newInstance(); - - wrappedProcessors.add(AnnotationProcessorWrapper.wrapProcessor(processor, expectedThrownException)); - - } catch (Exception e) { - throw new IllegalArgumentException("Passed processor " + processorType.getCanonicalName() + " cannot be instantiated.", e); - } - - } - - for (ProcessorWithExpectedException processor : this.processorsWithExpectedExceptions) { - - wrappedProcessors.add(AnnotationProcessorWrapper.wrapProcessor(processor.processorType, processor.throwable != null ? processor.throwable : expectedThrownException)); - - } - - // save cached wrapped processors - this.wrappedProcessors = wrappedProcessors; - - return wrappedProcessors; - - } - - public Set getModules() { - return modules; - } - - public Set getGeneratedJavaFileObjectChecks() { - return generatedJavaFileObjectChecks; - } - - public Set getCompilerMessageChecks() { - return compilerMessageChecks; - } - - public Map> getCompilerMessageCheckByKindMap() { - Map> map = new HashMap<>(); - - for (CompilerMessageCheck compilerMessageCheck : compilerMessageChecks) { - - List checkByKindList = map.get(compilerMessageCheck.getKind()); - if (checkByKindList == null) { - checkByKindList = new ArrayList<>(); - map.put(compilerMessageCheck.getKind(), checkByKindList); - - } - - checkByKindList.add(compilerMessageCheck); - } - - return map; - } - - public long countErrorMessageChecks() { - long count = 0; - - for (CompilerMessageCheck compilerMessageCheck : compilerMessageChecks) { - if (Diagnostic.Kind.ERROR.equals(compilerMessageCheck.getKind())) { - count++; - } - } - - return count; - } - - - public Set getGeneratedFileObjectChecks() { - return generatedFileObjectChecks; - } - - public Class getExpectedThrownException() { - return expectedThrownException; - } - - public PassInConfiguration getPassInConfiguration() { - return passInConfiguration; - } - - public static CompileTestConfiguration cloneConfiguration(CompileTestConfiguration compileTestConfiguration) { - return new CompileTestConfiguration(compileTestConfiguration); - } - - - @Override - public String toString() { - return "CompileTestConfiguration{\n" + - "\n\tcompilerOptions=" + compilerOptions + - ",\n\tsourceFiles=" + sourceFiles + - ",\n\t processors=" + processors + - ",\n\t processorTypes=" + processorTypes + - ",\n\t processorsWithExpectedExceptions=" + processorsWithExpectedExceptions + - ",\n\t expectedThrownException=" + expectedThrownException + - ",\n\t modules=" + modules + - ",\n\t compilationShouldSucceed=" + compilationShouldSucceed + - ",\n\t compilerMessageChecks=" + compilerMessageChecks + - ",\n\t generatedJavaFileObjectChecks=" + generatedJavaFileObjectChecks + - ",\n\t generatedFileObjectChecks=" + generatedFileObjectChecks + - ",\n\t passInConfiguration=" + passInConfiguration + - "\n" + - '}'; - } -} diff --git a/cute/src/main/java/io/toolisticon/cute/impl/package-info.java b/cute/src/main/java/io/toolisticon/cute/impl/package-info.java deleted file mode 100644 index f865bf5..0000000 --- a/cute/src/main/java/io/toolisticon/cute/impl/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * This package contains all internal used implementations not used in public api. - */ -package io.toolisticon.cute.impl; - diff --git a/cute/src/main/resources/AnnotationProcessorUnitTestClass.java b/cute/src/main/resources/AnnotationProcessorUnitTestClass.java index bbc7af1..7f2c1e3 100644 --- a/cute/src/main/resources/AnnotationProcessorUnitTestClass.java +++ b/cute/src/main/resources/AnnotationProcessorUnitTestClass.java @@ -2,85 +2,11 @@ import io.toolisticon.cute.TestAnnotation; -import java.util.Comparator; -import java.util.List; -import java.util.Map; - /** * Test class for annotation processor tools. + * Useed for as the entry point for executing unit tests. */ @TestAnnotation public class AnnotationProcessorUnitTestClass { - private String privateField; - protected String protectedField; - String packagePrivateField; - public String publicField; - public final String publicFinalField = ""; - public static String publicStaticField; - public transient String publicTransientField; - - enum TestEnum1 { - TEST11, TEST12; - } - - public enum TestEnum2 { - TEST21, TEST22; - } - - public static class EmbeddedStaticClass { - - } - - public Comparator comparatorWithAnonymousClass = new Comparator() { - @Override - public int compare(Long o1, Long o2) { - return 0; - } - }; - - - public class EmbeddedClass { - - } - - public class EmbeddedClassWithNoNoargConstructor { - - public EmbeddedClassWithNoNoargConstructor(String abs) { - - } - - } - - public abstract class AbstractEmbeddedClass { - - public abstract void abstractMethod(); - - } - - { - int x = 0; - } - - static { - int y = 0; - } - - public AnnotationProcessorUnitTestClass() { - - } - - public AnnotationProcessorUnitTestClass(String withParameter) { - - } - - public String methodWithReturnTypeAndParameters(Boolean first, String second) { - return ""; - } - - - public int testGenericsOnParameter(Map> o1, Map>> o2) { - return 0; - } - } diff --git a/cute/src/test/java/io/toolisticon/cute/impl/AnnotationProcessorWrapperTest.java b/cute/src/test/java/io/toolisticon/cute/AnnotationProcessorWrapperTest.java similarity index 85% rename from cute/src/test/java/io/toolisticon/cute/impl/AnnotationProcessorWrapperTest.java rename to cute/src/test/java/io/toolisticon/cute/AnnotationProcessorWrapperTest.java index 42de273..1e7d4b8 100644 --- a/cute/src/test/java/io/toolisticon/cute/impl/AnnotationProcessorWrapperTest.java +++ b/cute/src/test/java/io/toolisticon/cute/AnnotationProcessorWrapperTest.java @@ -1,9 +1,10 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; -import io.toolisticon.cute.CompileTestBuilder; +import io.toolisticon.cute.AnnotationProcessorWrapper; +import io.toolisticon.cute.Cute; import io.toolisticon.cute.TestAnnotation; -import io.toolisticon.cute.UnitTest; +import io.toolisticon.cute.UnitTestWithoutPassIn; import io.toolisticon.cute.testcases.TestAnnotationProcessor; import io.toolisticon.cute.testcases.TestAnnotationProcessorWithMissingNoArgConstructor; import org.hamcrest.MatcherAssert; @@ -234,15 +235,11 @@ public void getSupportedAnnotationsDefinedPerAnnotationCorrectly() { @Test public void process_withoutExpectedExceptionShouldSucceed() { + Cute.unitTest().when( + processingEnvironment -> { - CompileTestBuilder.unitTest().defineTest( - new UnitTest() { - @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element typeElement) { - - } - }) - .compilationShouldSucceed() + }) + .thenExpectThat().compilationSucceeds() .executeTest(); @@ -253,14 +250,10 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element typeEl public void process_testExpectedExceptionIsThrown_assertionShouldSucceed() { - CompileTestBuilder.unitTest().defineTest( - new UnitTest() { - @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element typeElement) { - throw new IllegalArgumentException(); - } - }) - .expectedThrownException(IllegalArgumentException.class) + Cute.unitTest().when(processingEnvironment -> { + throw new IllegalArgumentException(); + }) + .thenExpectThat().exceptionIsThrown(IllegalArgumentException.class) .executeTest(); @@ -270,14 +263,13 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element typeEl public void process_testExpectedExceptionNotThrown_assertionShouldFail() { try { - CompileTestBuilder.unitTest().defineTest( - new UnitTest() { + Cute.unitTest().when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element typeElement) { + public void unitTest(ProcessingEnvironment processingEnvironment) { } }) - .expectedThrownException(IllegalArgumentException.class) + .thenExpectThat().exceptionIsThrown(IllegalArgumentException.class) .executeTest(); } catch (Exception e) { MatcherAssert.assertThat(e.getMessage(), Matchers.containsString("Expected exception of type 'java.lang.IllegalArgumentException'")); @@ -289,14 +281,13 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element typeEl public void process_testUnexpectedExceptionWasThrown_assertionShouldFail() { try { - CompileTestBuilder.unitTest().defineTest( - new UnitTest() { + Cute.unitTest().when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element typeElement) { + public void unitTest(ProcessingEnvironment processingEnvironment) { throw new IllegalStateException(); } }) - .expectedThrownException(IllegalArgumentException.class) + .thenExpectThat().exceptionIsThrown(IllegalArgumentException.class) .executeTest(); } catch (Throwable e) { MatcherAssert.assertThat(e.getMessage(), Matchers.containsString("Expected exception of type 'java.lang.IllegalArgumentException' but exception of type 'java.lang.IllegalStateException' was thrown instead")); @@ -308,13 +299,11 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element typeEl public void process_testUnexpectedExceptionWasThrownWhenExpectedExceptionNotSet_assertionShouldFail() { try { - CompileTestBuilder.unitTest().defineTest( - new UnitTest() { - @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element typeElement) { - throw new IllegalStateException(); - } - }) + Cute.unitTest().when( + processingEnvironment -> { + throw new IllegalStateException(); + }) + .thenExpectThat().compilationFails() .executeTest(); } catch (Throwable e) { MatcherAssert.assertThat(e.getMessage(), Matchers.containsString("An unexpected exception of type 'java.lang.IllegalStateException'")); diff --git a/cute/src/test/java/io/toolisticon/cute/impl/CompileTestFileManagerTest.java b/cute/src/test/java/io/toolisticon/cute/CompileTestFileManagerTest.java similarity index 98% rename from cute/src/test/java/io/toolisticon/cute/impl/CompileTestFileManagerTest.java rename to cute/src/test/java/io/toolisticon/cute/CompileTestFileManagerTest.java index 0bb269a..728b75d 100644 --- a/cute/src/test/java/io/toolisticon/cute/impl/CompileTestFileManagerTest.java +++ b/cute/src/test/java/io/toolisticon/cute/CompileTestFileManagerTest.java @@ -1,5 +1,6 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; +import io.toolisticon.cute.CompileTestFileManager; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.Test; diff --git a/cute/src/test/java/io/toolisticon/cute/impl/CompileTestTest.java b/cute/src/test/java/io/toolisticon/cute/CompileTestTest.java similarity index 91% rename from cute/src/test/java/io/toolisticon/cute/impl/CompileTestTest.java rename to cute/src/test/java/io/toolisticon/cute/CompileTestTest.java index 5508dc8..fa87a78 100644 --- a/cute/src/test/java/io/toolisticon/cute/impl/CompileTestTest.java +++ b/cute/src/test/java/io/toolisticon/cute/CompileTestTest.java @@ -1,26 +1,15 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; -import io.toolisticon.cute.CompileTestBuilder; -import io.toolisticon.cute.Constants; +import io.toolisticon.cute.Cute; import io.toolisticon.cute.GeneratedFileObjectMatcher; -import io.toolisticon.cute.InvalidTestConfigurationException; import io.toolisticon.cute.JavaFileObjectUtils; -import io.toolisticon.cute.PassIn; -import io.toolisticon.cute.TestUtilities; import io.toolisticon.cute.UnitTest; -import org.hamcrest.MatcherAssert; -import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Test; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.VariableElement; -import javax.tools.Diagnostic; +import javax.lang.model.element.TypeElement; import javax.tools.FileObject; -import javax.tools.JavaFileObject; import javax.tools.StandardLocation; import java.io.IOException; import java.io.Writer; @@ -30,16 +19,16 @@ public class CompileTestTest { @Test public void test_UnitTest_checkMatchingFileObject() { - - CompileTestBuilder - .unitTest() - .defineTest(new UnitTest() { + Cute.unitTest() + .given().useCompilerOptions("-verbose ", " -source 1.7 ", "-target 1.7") + .when().passInElement().fromSourceFile("/AnnotationProcessorUnitTestTestClass.java") + .intoUnitTest(new UnitTest() { @Override public void unitTest(ProcessingEnvironment processingEnvironment, Element typeElement) { try { - FileObject fileObject = processingEnvironment.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "root", "Jupp.txt", typeElement); + FileObject fileObject = processingEnvironment.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "root", "Jupp.txt"); Writer writer = fileObject.openWriter(); writer.write("TATA!"); writer.close(); @@ -51,21 +40,24 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element typeEl } }) - .useCompilerOptions("-verbose ", " -source 1.7 ", "-target 1.7") - .compilationShouldSucceed() + .thenExpectThat().compilationSucceeds() + .andThat().fileObject(StandardLocation.SOURCE_OUTPUT, "root", "Jupp.txt").exists() - .expectThatFileObjectExists(StandardLocation.SOURCE_OUTPUT, "root", "Jupp.txt") - .expectThatFileObjectExists(StandardLocation.SOURCE_OUTPUT, "root", "Jupp.txt", JavaFileObjectUtils.readFromString("TATA!")) - .expectThatFileObjectExists(StandardLocation.SOURCE_OUTPUT, "root", "Jupp.txt", new GeneratedFileObjectMatcher() { + .andThat().fileObject(StandardLocation.SOURCE_OUTPUT, "root", "Jupp.txt").equals( JavaFileObjectUtils.readFromString("TATA!")) + + .andThat().fileObject(StandardLocation.SOURCE_OUTPUT, "root", "Jupp.txt").matches( new GeneratedFileObjectMatcher() { @Override public boolean check(FileObject fileObject) throws IOException { return fileObject.getCharContent(false).toString().contains("TAT"); } }) + + .executeTest(); } + /*- @Test public void test_UnitTest_checkNonMatchingFileObject() { @@ -378,4 +370,6 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element elemen } + + */ } diff --git a/cute/src/test/java/io/toolisticon/cute/impl/CompileTestUtilitiesTest.java b/cute/src/test/java/io/toolisticon/cute/CompileTestUtilitiesTest.java similarity index 98% rename from cute/src/test/java/io/toolisticon/cute/impl/CompileTestUtilitiesTest.java rename to cute/src/test/java/io/toolisticon/cute/CompileTestUtilitiesTest.java index b0cdb72..4740a37 100644 --- a/cute/src/test/java/io/toolisticon/cute/impl/CompileTestUtilitiesTest.java +++ b/cute/src/test/java/io/toolisticon/cute/CompileTestUtilitiesTest.java @@ -1,5 +1,6 @@ -package io.toolisticon.cute.impl; +package io.toolisticon.cute; +import io.toolisticon.cute.CompileTestUtilities; import io.toolisticon.cute.common.SimpleTestProcessor1; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; diff --git a/cute/src/test/java/io/toolisticon/cute/CompilerMessageCheckTest.java b/cute/src/test/java/io/toolisticon/cute/CompilerMessageCheckTest.java new file mode 100644 index 0000000..d60e13c --- /dev/null +++ b/cute/src/test/java/io/toolisticon/cute/CompilerMessageCheckTest.java @@ -0,0 +1,131 @@ +package io.toolisticon.cute; + +import io.toolisticon.cute.CuteApi; +import io.toolisticon.cute.Cute; +import io.toolisticon.cute.UnitTest; +import io.toolisticon.cute.UnitTestForTestingAnnotationProcessors; +import io.toolisticon.cute.common.SimpleTestProcessor1; +import org.junit.Test; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; + +/** + * Unit Test for checking correctness of compiler messages checks. + */ +public class CompilerMessageCheckTest { + + CuteApi.UnitTestRootInterface builder = Cute.unitTest(); + + @Test + public void testComplexCompilerMessageCheck_findMessage_withAll() { + + builder.when() + .passInElement().fromSourceFile("/AnnotationProcessorUnitTestTestClass.java") + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); + } + }) + .thenExpectThat().compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().atSource("/AnnotationProcessorUnitTestTestClass.java").atLine(13).atColumn(8).equals("ABC") + .executeTest(); + } + + @Test(expected = AssertionError.class) + public void testComplexCompilerMessageCheck_dontFindMessage_withAll_wrongSource() { + + builder.when().passInElement().fromSourceFile("/AnnotationProcessorUnitTestTestClass.java") + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); + } + }) + .thenExpectThat().compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().atSource("/XYZ.java").atLine(15).atColumn(8).equals("ABC") + .executeTest(); + + } + + @Test(expected = AssertionError.class) + public void testComplexCompilerMessageCheck_dontFindMessage_withAll_wrongLine() { + + builder.when().passInElement().fromSourceFile("/AnnotationProcessorUnitTestClass.java") + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); + } + }).thenExpectThat().compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().atSource("/AnnotationProcessorUnitTestClass.java").atLine(3).atColumn(8).equals("ABC") + .executeTest(); + + } + + @Test(expected = AssertionError.class) + public void testComplexCompilerMessageCheck_dontFindMessage_withAll_wrongColumn() { + + builder.when().passInElement().fromSourceFile("/AnnotationProcessorUnitTestClass.java") + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); + } + }).thenExpectThat().compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().atSource("/AnnotationProcessorUnitTestClass.java").atLine(13).atColumn(7).equals("ABC") + + .executeTest(); + + } + + @Test(expected = AssertionError.class) + public void testComplexCompilerMessageCheck_dontFindMessage_withAll_wrongMessage() { + + builder.when().passInElement().fromSourceFile("/AnnotationProcessorUnitTestClass.java") + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); + } + }).thenExpectThat().compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().atSource("/AnnotationProcessorUnitTestClass.java").atLine(13).atColumn(8).equals("BC") + + .executeTest(); + + } + + @Test + public void testComplexCompilerMessageCheck_findMessageSubstring_withAll() { + + builder.when().passInElement().fromSourceFile("/AnnotationProcessorUnitTestTestClass.java") + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); + } + }).thenExpectThat().compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().atSource("/AnnotationProcessorUnitTestTestClass.java").atLine(13).atColumn(8).contains("BC") + .executeTest(); + + } + + public void xyx(){ + builder.when() + .passInProcessor(SimpleTestProcessor1.class) + .andPassInElement().fromSourceFile("/AnnotationProcessorUnitTestClass.java") + .intoUnitTest(new UnitTestForTestingAnnotationProcessors() { + @Override + public void unitTest(SimpleTestProcessor1 unit, ProcessingEnvironment processingEnvironment, TypeElement element) { + + } + }) + .thenExpectThat() + .compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().atSource("/AnnotationProcessorUnitTestClass.java").atLine(13).atColumn(8).contains("BC") + .executeTest(); + } + +} diff --git a/cute/src/test/java/io/toolisticon/cute/CuteTest.java b/cute/src/test/java/io/toolisticon/cute/CuteTest.java new file mode 100644 index 0000000..df48990 --- /dev/null +++ b/cute/src/test/java/io/toolisticon/cute/CuteTest.java @@ -0,0 +1,973 @@ +package io.toolisticon.cute; + +import io.toolisticon.cute.common.SimpleTestProcessor1; +import io.toolisticon.fluapigen.validation.api.ValidatorException; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.mockito.Mockito; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; +import javax.tools.FileObject; +import javax.tools.JavaFileObject; +import javax.tools.StandardLocation; +import java.io.IOException; +import java.io.Writer; +import java.util.Arrays; + +/** + * Unit tests for {@link Cute}. + */ +public class CuteTest { + + @Test + public void test_UnitTest_successfulCompilation_build() { + + JavaFileObject testSource = Mockito.mock(JavaFileObject.class); + JavaFileObject expectedGeneratedSource = JavaFileObjectUtils.readFromString("Jupp.txt", "TATA!"); + Cute + .unitTest() + .when( + new UnitTestWithoutPassIn() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment) { + + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.MANDATORY_WARNING, "MANDATORY_WARNING"); + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "WARNING"); + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.NOTE, "NOTE"); + + + try { + FileObject fileObject = processingEnvironment.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "root", "Jupp.txt"); + Writer writer = fileObject.openWriter(); + writer.write("TATA!"); + writer.close(); + + + } catch (IOException e) { + + } + + } + }) + .thenExpectThat().compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().contains("WARNING") + .andThat().compilerMessage().ofKindMandatoryWarning().contains("MANDATORY_WARNING") + .andThat().compilerMessage().ofKindNote().contains("NOTE") + .executeTest(); + + + } + + + @Test + public void test_UnitTest_successfulCompilation_withInitializedProcessorUnderTest_build() { + + Cute.unitTest() + .when().passInProcessor(SimpleTestProcessor1.class) + .intoUnitTest(new UnitTestForTestingAnnotationProcessorsWithoutPassIn() { + @Override + public void unitTest(SimpleTestProcessor1 unit, ProcessingEnvironment processingEnvironment) { + + MatcherAssert.assertThat(unit.getProcessingEnvironment(), Matchers.equalTo(processingEnvironment)); + + } + }) + .thenExpectThat().compilationSucceeds() + .executeTest(); + } + + @PassIn + private static class PassInProcessorAndElement { + + } + + + @Test + public void test_UnitTest_successfulCompilation_withInitializedProcessorUnderTestAndPassIn_build() { + + Cute + .unitTest() + .when() + .passInProcessor(SimpleTestProcessor1.class) + .andPassInElement().fromClass(PassInProcessorAndElement.class) + .intoUnitTest(new UnitTestForTestingAnnotationProcessors() { + @Override + public void unitTest(SimpleTestProcessor1 unit, ProcessingEnvironment processingEnvironment, TypeElement typeElement) { + + MatcherAssert.assertThat(typeElement, Matchers.notNullValue()); + MatcherAssert.assertThat(typeElement.getQualifiedName().toString(), Matchers.is(PassInProcessorAndElement.class.getCanonicalName())); + + } + }) + .thenExpectThat() + .compilationSucceeds() + .executeTest(); + + + } + + /** + * @Retention(RetentionPolicy.RUNTIME) private static @interface CustomPassInAnnotation { + *

+ * } + * @CustomPassInAnnotation private static class PassInProcessorAndElementWithCustomAnnotation { + *

+ * } + * @Test public void test_UnitTest_successfulCompilation_withInitializedProcessorUnderTestAndPassInWithCustomAnnotation_build() { + *

+ * CuteFluentApiStarter + * .unitTest() + * .when() + * .passInProcessor(SimpleTestProcessor1.class) + * .andPassInElement().fromClass(PassInProcessorAndElementWithCustomAnnotation.class) + * .defineTestWithPassedInElement(SimpleTestProcessor1.class, PassInProcessorAndElementWithCustomAnnotation.class, CustomPassInAnnotation.class, new UnitTestForTestingAnnotationProcessors() { + * @Override public void unitTest(SimpleTestProcessor1 unit, ProcessingEnvironment processingEnvironment, TypeElement typeElement) { + *

+ * MatcherAssert.assertThat(typeElement, Matchers.notNullValue()); + * MatcherAssert.assertThat(typeElement.getQualifiedName().toString(), Matchers.is(PassInProcessorAndElementWithCustomAnnotation.class.getCanonicalName())); + *

+ * } + * }) + * .compilationShouldSucceed() + * .executeTest(); + *

+ *

+ * } + */ + + @Test + public void test_UnitTest_failingCompilation_build() { + + JavaFileObject testSource = Mockito.mock(JavaFileObject.class); + JavaFileObject expectedGeneratedSource = Mockito.mock(JavaFileObject.class); + + Cute + .unitTest() + .when().unitTestWithoutPassIn(new UnitTestWithoutPassIn() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment) { + + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.ERROR, "ERROR"); + } + }) + .thenExpectThat() + .compilationFails() + .andThat().compilerMessage().ofKindError().contains("ERROR") + .executeTest(); + + + } + +/*- + private void assertCompilerMessages(Set compilerMessageChecks, Diagnostic.Kind kind, CompileTestConfiguration.ComparisonKind comparisonKind, String... expectedMessages) { + + List configuredExpectedMessages = new ArrayList<>(); + + Iterator iterator = compilerMessageChecks.iterator(); + while (iterator.hasNext()) { + CompileTestConfiguration.CompilerMessageCheck element = iterator.next(); + + MatcherAssert.assertThat(element.getComparisonKind(), Matchers.is(comparisonKind)); + MatcherAssert.assertThat(element.getKind(), Matchers.is(kind)); + + configuredExpectedMessages.add(element.getExpectedMessage()); + + } + + MatcherAssert.assertThat(configuredExpectedMessages + , Matchers.containsInAnyOrder(expectedMessages)); + } + + + @Test + public void test_addWarningChecks() { + + CuteFluentApiStarter. builder = CuteFluentApiStarter + .blackBoxTest() + .compilationTest() + .expectWarningMessageThatContains("WARN1"); + + + assertCompilerMessages(builder.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.WARNING, CompileTestConfiguration.ComparisonKind.CONTAINS, "WARN1"); + + CompileTestBuilder.CompilationTestBuilder builder2 = builder + .expectWarningMessageThatContains("WARN2"); + + assertCompilerMessages(builder2.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.WARNING, CompileTestConfiguration.ComparisonKind.CONTAINS, "WARN1", "WARN2"); + + + CompileTestBuilder.CompilationTestBuilder builder3 = builder2 + .expectWarningMessageThatContains() + .expectWarningMessageThatContains(null); + + + assertCompilerMessages(builder3.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.WARNING, CompileTestConfiguration.ComparisonKind.CONTAINS, "WARN1", "WARN2"); + + + } +*/ + /*- + public void test_addMandatoryWarningChecks() { + + CompileTestBuilder.CompilationTestBuilder builder = CompileTestBuilder + .compilationTest() + .expectMandatoryWarningMessageThatContains("MWARN1"); + + assertCompilerMessages(builder.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.MANDATORY_WARNING, CompileTestConfiguration.ComparisonKind.CONTAINS, "MWARN1"); + + + CompileTestBuilder.CompilationTestBuilder builder2 = builder + .expectMandatoryWarningMessageThatContains("MWARN2"); + + assertCompilerMessages(builder2.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.MANDATORY_WARNING, CompileTestConfiguration.ComparisonKind.CONTAINS, "MWARN1", "MWARN2"); + + + CompileTestBuilder.CompilationTestBuilder builder3 = builder2 + .expectMandatoryWarningMessageThatContains() + .expectMandatoryWarningMessageThatContains(null); + + + assertCompilerMessages(builder3.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.MANDATORY_WARNING, CompileTestConfiguration.ComparisonKind.CONTAINS, "MWARN1", "MWARN2"); + + + } + + public void test_addNoteChecks() { + + CompileTestBuilder.CompilationTestBuilder builder = CompileTestBuilder + .compilationTest() + .expectNoteMessageThatContains("NOTE1"); + + + assertCompilerMessages(builder.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.NOTE, CompileTestConfiguration.ComparisonKind.CONTAINS, "NOTE1"); + + + CompileTestBuilder.CompilationTestBuilder builder2 = builder + .expectNoteMessageThatContains("NOTE2"); + + + assertCompilerMessages(builder2.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.NOTE, CompileTestConfiguration.ComparisonKind.CONTAINS, "NOTE1", "NOTE2"); + + + CompileTestBuilder.CompilationTestBuilder builder3 = builder2 + .expectNoteMessageThatContains() + .expectNoteMessageThatContains(null); + + + assertCompilerMessages(builder3.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.NOTE, CompileTestConfiguration.ComparisonKind.CONTAINS, "NOTE1", "NOTE2"); + + + } + + public void test_addErrorChecks() { + + CompileTestBuilder.CompilationTestBuilder builder = CompileTestBuilder + .compilationTest() + .expectErrorMessageThatContains("ERROR1"); + + + assertCompilerMessages(builder.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.ERROR, CompileTestConfiguration.ComparisonKind.CONTAINS, "ERROR1"); + + + CompileTestBuilder.CompilationTestBuilder builder2 = builder + .expectErrorMessageThatContains("ERROR2"); + + assertCompilerMessages(builder2.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.ERROR, CompileTestConfiguration.ComparisonKind.CONTAINS, "ERROR1", "ERROR2"); + + + CompileTestBuilder.CompilationTestBuilder builder3 = builder2 + .expectErrorMessageThatContains() + .expectErrorMessageThatContains(null); + + assertCompilerMessages(builder3.createCompileTestConfiguration().getCompilerMessageChecks(), Diagnostic.Kind.ERROR, CompileTestConfiguration.ComparisonKind.CONTAINS, "ERROR1", "ERROR2"); + + + } + + @Test + public void test_compilationShouldSucceed() { + + CompileTestBuilder.CompilationTestBuilder builder = CompileTestBuilder + .compilationTest(); + + MatcherAssert.assertThat(builder.compilationShouldSucceed().createCompileTestConfiguration().getCompilationShouldSucceed(), Matchers.is(Boolean.TRUE)); + MatcherAssert.assertThat(builder.compilationShouldFail().createCompileTestConfiguration().getCompilationShouldSucceed(), Matchers.is(Boolean.FALSE)); + + + } + + @Test + public void test_addSource() { + + JavaFileObject testSource1 = Mockito.mock(JavaFileObject.class); + JavaFileObject testSource2 = Mockito.mock(JavaFileObject.class); + + CompileTestBuilder.CompilationTestBuilder builder = CompileTestBuilder + .compilationTest() + .addSources(testSource1) + .addSources(testSource2); + + MatcherAssert.assertThat(builder.createCompileTestConfiguration().getSourceFiles(), Matchers.containsInAnyOrder(testSource1, testSource2)); + + + } + + @Test + public void test_addSourceFromResources() { + + final String resource = "/compiletests/TestClass.java"; + + CompileTestBuilder.CompilationTestBuilder builder = CompileTestBuilder + .compilationTest() + .addSources(resource); + + MatcherAssert.assertThat(builder.createCompileTestConfiguration().getSourceFiles().iterator().next().getName().toString(), Matchers.is(resource)); + + } + + + @Test + public void test_addSourceFromString_compileTest() { + + final String content ="package io.toolisticon.annotationprocessortoolkit.testhelper;" + System.lineSeparator() + + "public class TestClass {" + System.lineSeparator() + + "}"; + + CuteApi.BlackBoxTestFinalGivenInterface builder = Cute + .blackBoxTest() + .given().processors(AbstractProcessor.class) + .andSourceFile("io.toolisticon.annotationprocessortoolkit.testhelper.TestClass", content); + + // Check if source name is correct + MatcherAssert.assertThat(builder..createCompileTestConfiguration().getSourceFiles().iterator().next().getName().toString(), Matchers.is("/io/toolisticon/annotationprocessortoolkit/testhelper/TestClass.java")); + + // Check if classes are compiled in the end + builder.compilationShouldSucceed() + .expectThatJavaFileObjectExists(StandardLocation.CLASS_OUTPUT,"io.toolisticon.annotationprocessortoolkit.testhelper.TestClass", JavaFileObject.Kind.CLASS) + .executeTest(); + } + + + @Test + public void test_addSourceFromString_unitTest() { + + final String content ="package io.toolisticon.annotationprocessortoolkit.testhelper;" + System.lineSeparator() + + "import io.toolisticon.cute.PassIn;" + System.lineSeparator() + + "@PassIn" + System.lineSeparator() + + "public class TestClass {" + System.lineSeparator() + + "}"; + + CuteFluentApi.PassInElementInterface builder = (CuteFluentApi.PassInElementInterface) CuteFluentApiStarter + .unitTest() + .when().passInElement().fromStringSource("io.toolisticon.annotationprocessortoolkit.testhelper.TestClass", content); + + // Check if source name is correct + MatcherAssert.assertThat(builder.createCompileTestConfiguration().getSourceFiles().iterator().next().getName().toString(), Matchers.is("/io/toolisticon/annotationprocessortoolkit/testhelper/TestClass.java")); + + // Check if classes are compiled in the end + builder.defineTest(PassIn.class, new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + MatcherAssert.assertThat("io.toolisticon.annotationprocessortoolkit.testhelper.TestClass" , Matchers.is(element.getQualifiedName().toString())); + } + }).compilationShouldSucceed() + .expectThatJavaFileObjectExists(StandardLocation.CLASS_OUTPUT,"io.toolisticon.annotationprocessortoolkit.testhelper.TestClass", JavaFileObject.Kind.CLASS) + .executeTest(); + + } + + @Test + public void test_useProcessors() { + + Class testProcessor1 = SimpleTestProcessor1.class; + Class testProcessor2 = SimpleTestProcessor2.class; + + CompileTestBuilder.CompilationTestBuilder builder = CompileTestBuilder + .compilationTest() + .addProcessors(testProcessor1) + .addProcessors(testProcessor2) + .addProcessors((Class) null); + + + MatcherAssert.assertThat(builder.createCompileTestConfiguration().getProcessorTypes(), Matchers.containsInAnyOrder(testProcessor1, testProcessor2)); + + + } + + @Test + public void test_useProcessorAndExpectException() { + + Class testProcessor1 = SimpleTestProcessor1.class; + Class testProcessor2 = SimpleTestProcessor2.class; + + CompileTestBuilder.CompilationTestBuilder builder = CompileTestBuilder + .compilationTest() + .addProcessorWithExpectedException(testProcessor1, IllegalArgumentException.class) + .addProcessorWithExpectedException(testProcessor2, IllegalStateException.class); + + + MatcherAssert.assertThat(builder.createCompileTestConfiguration().getProcessorsWithExpectedExceptions(), Matchers.hasSize(2)); + + + } + + @Test + public void test_useSource_addSingleSource() { + + JavaFileObject javaFileObject = Mockito.mock(JavaFileObject.class); + + CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + .unitTest() + .useSource(javaFileObject); + + MatcherAssert.assertThat(builder.createCompileTestConfiguration().getSourceFiles(), Matchers.contains(javaFileObject)); + + } + + @Test + public void test_useSource_addSourceTwice_onlySecondSourceShouldBeUsed() { + + JavaFileObject javaFileObject1 = Mockito.mock(JavaFileObject.class); + JavaFileObject javaFileObject2 = Mockito.mock(JavaFileObject.class); + + CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + .unitTest() + .useSource(javaFileObject1) + .useSource(javaFileObject2); + + MatcherAssert.assertThat(builder.createCompileTestConfiguration().getSourceFiles(), Matchers.contains(javaFileObject2)); + + } + + @Test(expected = IllegalArgumentException.class) + public void test_useSource_addNullValuedSource_asJavaFileObject() { + + + CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + .unitTest() + .useSource((JavaFileObject) null); + + + } + + @Test(expected = IllegalArgumentException.class) + public void test_useSource_addNullValuedSource_asString() { + + + CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + .unitTest() + .useSource((String) null); + + + } + + @Test(expected = IllegalArgumentException.class) + public void test_useProcessor_addNullValuedProcessor() { + + + CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + .unitTest() + .useProcessor((Processor) null); + + + } + + @Test(expected = IllegalArgumentException.class) + public void test_useProcessor_addNullValuedUnitTestProcessor() { + + + CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + .unitTest() + .defineTest((UnitTest) null); + + + } + + @Test(expected = IllegalArgumentException.class) + public void test_useProcessor_nonInstantiableConstructorForProcessorUnderTest() { + + + CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + .unitTest() + .defineTest(AbstractProcessor.class, new UnitTestForTestingAnnotationProcessors() { + @Override + public void unitTest(AbstractProcessor unit, ProcessingEnvironment processingEnvironment, TypeElement typeElement) { + + } + }); + + + } + + @Test(expected = IllegalArgumentException.class) + public void test_useProcessor_nullProcessorUnderTestClass() { + + + CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + .unitTest() + .defineTest(null, new UnitTestForTestingAnnotationProcessors() { + @Override + public void unitTest(AbstractProcessor unit, ProcessingEnvironment processingEnvironment, TypeElement typeElement) { + + } + }); + + + } + + + public static class TestProcessor extends AbstractProcessor { + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + return false; + } + } + + @Test + public void test_useProcessor_nonMatchingElement1() { + + + try { + CompileTestBuilder + .unitTest() + .defineTest(TestProcessor.class, new UnitTestForTestingAnnotationProcessors() { + @Override + public void unitTest(TestProcessor unit, ProcessingEnvironment processingEnvironment, ExecutableElement typeElement) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.NOTE, "ABC"); + } + }) + .executeTest(); + } catch (AssertionError e) { + + MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(Constants.Messages.UNIT_TEST_PRECONDITION_INCOMPATIBLE_ELEMENT_TYPE.getMessagePattern())); + + return; + } + + throw new AssertionError("Expected AssertionError to be thrown."); + + } + + @Test + public void test_useProcessor_nonMatchingElement2() { + + try { + CompileTestBuilder + .unitTest() + .defineTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, ExecutableElement typeElement) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.NOTE, "ABC"); + } + }) + .executeTest(); + } catch (AssertionError e) { + + MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(Constants.Messages.UNIT_TEST_PRECONDITION_INCOMPATIBLE_ELEMENT_TYPE.getMessagePattern())); + + return; + } + + throw new AssertionError("Expected AssertionError to be thrown."); + + } + + @Test + public void test_useProcessor_withoutGenericTypeParameters1() { + + CompileTestBuilder + .unitTest() + .defineTest(TestProcessor.class, new UnitTestForTestingAnnotationProcessors() { + @Override + public void unitTest(Processor unit, ProcessingEnvironment processingEnvironment, Element typeElement) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.NOTE, "ABC"); + } + }) + .executeTest(); + + } + + @Test + public void test_useProcessor_withoutGenericTypeParameters2() { + + CompileTestBuilder + .unitTest() + .defineTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, Element element) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.NOTE, "ABC"); + } + }) + .executeTest(); + + + } + + @Test + public void test_useProcessor_nonMatchingAnnotationType() { + + CompileTestBuilder + .unitTest() + .defineTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, Element element) { + processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); + } + }) + .expectWarningMessage().thatContains("ABC") + .executeTest(); + + + } + + @Test(expected = IllegalArgumentException.class) + public void test_useProcessor_nullValued_Processor() { + CompileTestBuilder.unitTest().useProcessor((Processor) null); + } + + @Test(expected = IllegalArgumentException.class) + public void test_useProcessor_nullValued_UnitTestProcessor() { + CompileTestBuilder.unitTest().defineTest((UnitTest) null); + } + + @Test(expected = IllegalArgumentException.class) + public void test_useProcessor_nullValued_UnitTestProcessor2() { + CompileTestBuilder.unitTest().defineTest(AbstractProcessor.class, null); + } + + + @Test(expected = IllegalArgumentException.class) + public void test_CompileTimeTestBuilder_useProcessorAndExpectException_addNullValuedProcessor() { + + CompileTestBuilder + .compilationTest() + .addProcessorWithExpectedException(null, IllegalStateException.class); + + + } + + private static class SimpleTestProcessor extends AbstractProcessor { + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + return false; + } + } + + @Test(expected = IllegalArgumentException.class) + public void test_CompileTimeTestBuilder_useProcessorAndExpectException_addNullValuedException() { + + CompileTestBuilder + .compilationTest() + .addProcessorWithExpectedException(SimpleTestProcessor.class, null); + + + } + + @Test(expected = IllegalStateException.class) + public void test_CompileTimeTestBuilder_testCompilation_noSourceFiles() { + + CompileTestBuilder + .compilationTest() + .executeTest(); + + + } + + @Test + public void test_useModules() { + + MatcherAssert.assertThat(CompileTestBuilder.compilationTest().useModules("ABC", "DEF").compileTestConfiguration.getModules(), Matchers.contains("ABC", "DEF")); + + } + + @Test + public void test_addCompilerMessageCheck() { + + CompileTestConfiguration configuration = CompileTestBuilder.compilationTest().expectErrorMessage().atSource("XYZ").atLineNumber(5L).atColumnNumber(6L).withLocale(Locale.ENGLISH).thatContains("ABC").compileTestConfiguration; + CompileTestConfiguration.CompilerMessageCheck compilerMessageCheck = configuration.getCompilerMessageChecks().iterator().next(); + MatcherAssert.assertThat(compilerMessageCheck.getSource(), Matchers.is("XYZ")); + MatcherAssert.assertThat(compilerMessageCheck.getKind(), Matchers.is(Diagnostic.Kind.ERROR)); + MatcherAssert.assertThat(compilerMessageCheck.getLineNumber(), Matchers.is(5L)); + MatcherAssert.assertThat(compilerMessageCheck.getColumnNumber(), Matchers.is(6L)); + MatcherAssert.assertThat(compilerMessageCheck.getLocale(), Matchers.is(Locale.ENGLISH)); + MatcherAssert.assertThat(compilerMessageCheck.getComparisonKind(), Matchers.is(CompileTestConfiguration.ComparisonKind.CONTAINS)); + MatcherAssert.assertThat(compilerMessageCheck.getExpectedMessage(), Matchers.is("ABC")); + + } + */ + + @Test + public void test_passInViaSourceCode_multipleAnnotated_withOnePassIn() { + + Cute + .unitTest() + .when() + .passInElement().fromSourceFile("/compiletests/passintest/PassInTestClass.java") + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + MatcherAssert.assertThat(element, Matchers.notNullValue()); + MatcherAssert.assertThat(element.getSimpleName().toString(), Matchers.is("InnerTestClass")); + } + }) + .executeTest(); + + } + + @Test + public void test_passInViaSourceCode_multipleAnnotated_withoutPassIn() { + + try { + Cute + .unitTest() + .when() + .passInElement().fromSourceFile("/compiletests/passintest/PassInTestClassMultipleAnnotatedWithoutPassIn.java") + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + throw new AssertionError("should have thrown assertion error!"); + } + }) + .executeTest(); + + } catch (AssertionError e) { + MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(String.format(Constants.Messages.MESSAGE_PROCESSOR_HASNT_BEEN_APPLIED.getMessagePattern(), UnitTestAnnotationProcessorClass.class.getCanonicalName(), Arrays.asList(PassIn.class.getCanonicalName())))); + return; + } + + throw new AssertionError("Expected AssertionError to be thrown."); + + } + + @Test + public void test_passInViaSourceCode_multipleAnnotated_withMultiplePassIn() { + + try { + Cute + .unitTest() + .when() + .passInElement().fromSourceFile("/compiletests/passintest/PassInTestClassMultipleAnnotatedWithMultiplePassIn.java") + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + throw new AssertionError("should have thrown assertion error!"); + } + }) + .executeTest(); + + } catch (AssertionError e) { + MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(String.format(Constants.Messages.UNIT_TEST_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT_WITH_PASSIN_ANNOTATION.getMessagePattern()))); + return; + } + + throw new AssertionError("Expected AssertionError to be thrown."); + + } + + @Test + public void test_passInViaSourceCode_withNonMatchingElementType() { + + try { + Cute + .unitTest() + .given() + .useSourceFile("/compiletests/passintest/PassInTestClass.java") + .when() + .passInElement().fromGivenSourceFiles() + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, ExecutableElement element) { + throw new AssertionError("should have thrown assertion error!"); + } + }) + .executeTest(); + + } catch (AssertionError e) { + MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(Constants.Messages.UNIT_TEST_PRECONDITION_INCOMPATIBLE_ELEMENT_TYPE.getMessagePattern())); + return; + } + + throw new AssertionError("Expected AssertionError to be thrown."); + + } + + @Test + public void test_passInViaSourceCode_withProcessorPassIn_withMatchingElementButClassCastException() { + + + Cute + .unitTest() + .given().useSourceFile("/compiletests/passintest/PassInTestClass.java") + .when() + .passInElement().fromGivenSourceFiles() + .andPassInProcessor(SimpleTestProcessor1.class) + .intoUnitTest(new UnitTestForTestingAnnotationProcessors() { + @Override + public void unitTest(SimpleTestProcessor1 unit, ProcessingEnvironment processingEnvironment, TypeElement element) { + throw new ClassCastException("Test Class Cast Exception"); + } + }) + .thenExpectThat() + .exceptionIsThrown(ClassCastException.class) + .executeTest(); + + } + + @PassIn + static class PassInClass { + + } + + + @Test + public void test_passIn_withNonMatchingElementType() { + + try { + Cute + .unitTest() + .when() + .passInElement().fromClass(PassInClass.class) + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, ExecutableElement element) { + throw new AssertionError("should have thrown assertion error!"); + } + }) + .executeTest(); + + } catch (AssertionError e) { + MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(Constants.Messages.UNIT_TEST_PRECONDITION_INCOMPATIBLE_ELEMENT_TYPE.getMessagePattern())); + return; + } + + throw new AssertionError("Expected AssertionError to be thrown."); + + } + + @Test + public void test_passIn_withMatchingElementButClassCastException() { + + Cute + .unitTest() + .when() + .passInElement().fromClass(PassInClass.class) + .intoUnitTest(new UnitTest() { + @Override + public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { + throw new ClassCastException("Test Class Cast Exception"); + } + }) + .thenExpectThat() + .exceptionIsThrown(ClassCastException.class) + .executeTest(); + + } + + @Test + public void test_passIn_withProcessorPassIn_withNonMatchingElementType() { + + try { + Cute + .unitTest() + .when() + .passInProcessor(SimpleTestProcessor1.class) + .andPassInElement().fromClass(PassInClass.class) + .intoUnitTest(new UnitTestForTestingAnnotationProcessors() { + @Override + public void unitTest(SimpleTestProcessor1 unit, ProcessingEnvironment processingEnvironment, ExecutableElement element) { + throw new AssertionError("should have thrown assertion error!"); + } + }) + .executeTest(); + + } catch (AssertionError e) { + MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(Constants.Messages.UNIT_TEST_PRECONDITION_INCOMPATIBLE_ELEMENT_TYPE.getMessagePattern())); + return; + } + + throw new AssertionError("Expected AssertionError to be thrown."); + + } + + @Test + public void test_passIn_withProcessorPassIn_withMatchingElementButClassCastException() { + + Cute + .unitTest() + .when() + .passInProcessor(SimpleTestProcessor1.class) + .andPassInElement().fromClass(PassInClass.class) + .intoUnitTest(new UnitTestForTestingAnnotationProcessors() { + @Override + public void unitTest(SimpleTestProcessor1 unit, ProcessingEnvironment processingEnvironment, Element element) { + throw new ClassCastException("Test Class Cast Exception"); + } + }) + .thenExpectThat() + .exceptionIsThrown(ClassCastException.class) + .executeTest(); + + } + + + @Test(expected = ValidatorException.class) + public void blackBoxTest_nullValuedProcessor() { + Cute.blackBoxTest().given().processors(null); + } + + @Test(expected = ValidatorException.class) + public void blackBoxTest_nullValuedProcessorInArray() { + Cute.blackBoxTest().given().processors(null, null); + } + + @Test() + public void blackBoxTest_emptyProcessors_shouldJustCompileCode() { + Cute.blackBoxTest().given().processors() + .andSourceFiles("/TestClass.java") + .whenCompiled() + .thenExpectThat() + .compilationSucceeds() + .andThat().generatedClass("io.toolisticon.cute.TestClass").exists() + .executeTest(); + } + + @Test() + public void blackBoxTest_noProcessors_shouldJustCompileCode() { + Cute.blackBoxTest().given().noProcessors() + .andSourceFiles("/TestClass.java") + .whenCompiled() + .thenExpectThat() + .compilationSucceeds() + .andThat().generatedClass("io.toolisticon.cute.TestClass").exists() + .executeTest(); + } + + @Test + public void blackBoxTest_executeTest_WithoutChecks_SuccessfulCompilation() { + Cute.blackBoxTest().given().noProcessors() + .andSourceFiles("/TestClass.java") + .executeTest(); + } + + @Test + public void blackBoxTest_executeTest_WithoutChecks_FailedCompilation() { + try { + Cute.blackBoxTest().given().noProcessors() + .andSourceFiles("/BrokenTestClass.java") + .executeTest(); + + } catch (AssertionError e) { + if (e.getMessage().contains("Compilation should have succeeded but failed")) { + return; + } + } + throw new AssertionError("Should have got Assertion error that compilation was expected to be successful but failed"); + } + + +} diff --git a/cute/src/test/java/io/toolisticon/cute/impl/CompileTestConfigurationTest.java b/cute/src/test/java/io/toolisticon/cute/impl/CompileTestConfigurationTest.java deleted file mode 100644 index 3e48347..0000000 --- a/cute/src/test/java/io/toolisticon/cute/impl/CompileTestConfigurationTest.java +++ /dev/null @@ -1,652 +0,0 @@ -package io.toolisticon.cute.impl; - -import io.toolisticon.cute.GeneratedFileObjectMatcher; -import io.toolisticon.cute.TestAnnotation; -import io.toolisticon.cute.common.SimpleTestProcessor1; -import io.toolisticon.cute.common.SimpleTestProcessor2; -import io.toolisticon.cute.common.SimpleTestProcessor3; -import org.hamcrest.MatcherAssert; -import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import javax.annotation.processing.Processor; -import javax.tools.FileObject; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject; -import javax.tools.StandardLocation; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -/** - * Unit test for {@link CompileTestConfiguration} - */ -public class CompileTestConfigurationTest { - - private CompileTestConfiguration unit; - - // compiler options - private final String compilerOption1 = "verbose"; - private final String compilerOption2 = "source 1.7"; - - - // source files - private final JavaFileObject sourceJavaFileObject1 = Mockito.mock(JavaFileObject.class); - private final JavaFileObject sourceJavaFileObject2 = Mockito.mock(JavaFileObject.class); - private final JavaFileObject sourceJavaFileObject3 = Mockito.mock(JavaFileObject.class); - - // processors - private final Processor processor1 = Mockito.mock(Processor.class); - private final Processor processor2 = Mockito.mock(Processor.class); - private final Processor processor3 = Mockito.mock(Processor.class); - - // processorsWithExpectedExceptions - private final CompileTestConfiguration.ProcessorWithExpectedException processorWithExpectedException1 = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, IllegalStateException.class); - private final CompileTestConfiguration.ProcessorWithExpectedException processorWithExpectedException2 = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor2.class, IllegalArgumentException.class); - private final CompileTestConfiguration.ProcessorWithExpectedException processorWithExpectedException3 = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor3.class, IllegalThreadStateException.class); - - // expectedThrownException - private final Class expectedThrownException = IllegalStateException.class; - - // compilationShouldSucceed - private final boolean compilationShouldSucceed = true; - - // message checks - private final String message1 = "MESSAGE1"; - private final String message2 = "MESSAGE2"; - private final String message3 = "MESSAGE3"; - - // FileObjects - private final JavaFileObject jfo1 = Mockito.mock(JavaFileObject.class); - private final JavaFileObject jfo2 = Mockito.mock(JavaFileObject.class); - private final FileObject fo1 = Mockito.mock(FileObject.class); - private final FileObject fo2 = Mockito.mock(FileObject.class); - - // generatedJavaFileObjectChecks - private final CompileTestConfiguration.GeneratedJavaFileObjectCheck generatedJavaFileObjectChecks3 = new CompileTestConfiguration.GeneratedJavaFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, StandardLocation.SOURCE_OUTPUT, - "className3", JavaFileObject.Kind.SOURCE, Mockito.mock(GeneratedFileObjectMatcher.class)); - private final CompileTestConfiguration.GeneratedJavaFileObjectCheck generatedJavaFileObjectChecks4 = new CompileTestConfiguration.GeneratedJavaFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, StandardLocation.CLASS_OUTPUT, - "className4", JavaFileObject.Kind.CLASS, Mockito.mock(GeneratedFileObjectMatcher.class)); - - // generatedFileObjectChecks - private final CompileTestConfiguration.GeneratedFileObjectCheck generatedFileObjectChecks3 = new CompileTestConfiguration.GeneratedFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, StandardLocation.SOURCE_OUTPUT, - "package3", "relativeName3", toArray(Mockito.mock(GeneratedFileObjectMatcher.class))); - private final CompileTestConfiguration.GeneratedFileObjectCheck generatedFileObjectChecks4 = new CompileTestConfiguration.GeneratedFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, StandardLocation.CLASS_OUTPUT, - "package4", "relativeName4", toArray(Mockito.mock(GeneratedFileObjectMatcher.class))); - - - @SafeVarargs - private static ARRAY_TYPE[] toArray(ARRAY_TYPE... elements) { - return elements; - } - - @Before - public void init() { - unit = new CompileTestConfiguration(); - } - - - @Test - public void compilerOptions_addAndGet() { - - unit.addCompilerOptions(compilerOption1, compilerOption2); - - // do assertion - assertCompilerOptions(unit); - - } - - private void assertCompilerOptions(CompileTestConfiguration configuration) { - MatcherAssert.assertThat(configuration.getCompilerOptions(), Matchers.containsInAnyOrder(compilerOption1, compilerOption2)); - } - - @Test - public void sourceFiles_addAndGet() { - - unit.addSourceFiles(sourceJavaFileObject1, sourceJavaFileObject2, sourceJavaFileObject3); - - // do assertion - assertSourceFiles(unit); - - } - - private void assertSourceFiles(CompileTestConfiguration configuration) { - MatcherAssert.assertThat(configuration.getSourceFiles(), Matchers.contains(sourceJavaFileObject1, sourceJavaFileObject2, sourceJavaFileObject3)); - } - - - @Test - public void processors_addAndGet() { - - unit.addProcessors(processor1, processor2, processor3); - - // do assertion - assertProcessors(unit); - - } - - private void assertProcessors(CompileTestConfiguration configuration) { - MatcherAssert.assertThat(configuration.getProcessors(), Matchers.containsInAnyOrder(processor1, processor2, processor3)); - } - - @Test - public void processorTypes_addAndGet() { - - unit.addProcessorTypes(SimpleTestProcessor1.class, SimpleTestProcessor2.class, SimpleTestProcessor3.class); - - // do assertion - assertProcessorTypes(unit); - - } - - private void assertProcessorTypes(CompileTestConfiguration configuration) { - MatcherAssert.assertThat(configuration.getProcessorTypes(), Matchers.containsInAnyOrder(SimpleTestProcessor1.class, (Class) SimpleTestProcessor2.class, SimpleTestProcessor3.class)); - } - - @Test - public void processorsWithExpectedExceptions_addAndGet() { - - unit.addProcessorWithExpectedException(processorWithExpectedException1.getProcessorType(), processorWithExpectedException1.getThrowable()); - unit.addProcessorWithExpectedException(processorWithExpectedException2.getProcessorType(), processorWithExpectedException2.getThrowable()); - unit.addProcessorWithExpectedException(processorWithExpectedException3.getProcessorType(), processorWithExpectedException3.getThrowable()); - - // do assertion - assertProcessorsWithExpectedExceptions(unit); - - } - - private void assertProcessorsWithExpectedExceptions(CompileTestConfiguration configuration) { - MatcherAssert.assertThat(configuration.getProcessorsWithExpectedExceptions(), Matchers.containsInAnyOrder(processorWithExpectedException1, processorWithExpectedException2, processorWithExpectedException3)); - } - - @Test - public void modules_addAndGet() { - - unit.addModules("spiap.api", "java.compiler"); - unit.addModules("java.base"); - - - // do assertion - assertModules(unit); - - } - - private void assertModules(CompileTestConfiguration configuration) { - MatcherAssert.assertThat(configuration.getModules(), Matchers.containsInAnyOrder("spiap.api", "java.compiler", "java.base")); - } - - @Test - public void expectedThrownException_setAndGet() { - - unit.setExpectedThrownException(expectedThrownException); - - // do assertion - assertExpectedThrownException(unit, expectedThrownException); - - } - - @Test - public void expectedThrownException_overwriteValue() { - - expectedThrownException_setAndGet(); - - unit.setExpectedThrownException(RuntimeException.class); - - // do assertion - assertExpectedThrownException(unit, RuntimeException.class); - - } - - private void assertExpectedThrownException(CompileTestConfiguration configuration, Class expectedThrownException) { - MatcherAssert.assertThat(configuration.getExpectedThrownException(), Matchers.equalTo((Class) expectedThrownException)); - } - - - @Test - public void compilationShouldSucceed_setAndGet() { - - unit.setCompilationShouldSucceed(compilationShouldSucceed); - - // do assertion - assertCompilationShouldSucceed(unit, compilationShouldSucceed); - - } - - @Test - public void compilationShouldSucceed_overwriteValue() { - - expectedThrownException_setAndGet(); - - unit.setCompilationShouldSucceed(false); - - // do assertion - assertCompilationShouldSucceed(unit, false); - - } - - private void assertCompilationShouldSucceed(CompileTestConfiguration configuration, Boolean compilationShouldSucceed) { - MatcherAssert.assertThat(configuration.getCompilationShouldSucceed(), Matchers.equalTo(compilationShouldSucceed)); - } - - - @Test - public void compilerMessageCheck_setAndGet() { - - unit.addNoteMessageCheck(CompileTestConfiguration.ComparisonKind.CONTAINS, message1, message2); - unit.addNoteMessageCheck(CompileTestConfiguration.ComparisonKind.CONTAINS, message3); - - // do assertion - assertMessages(unit.getCompilerMessageChecks()); - - } - - - private void assertMessages(Set messageSet) { - - List messages = new ArrayList<>(); - - Iterator iterator = messageSet.iterator(); - while (iterator.hasNext()) { - messages.add(iterator.next().getExpectedMessage()); - } - - MatcherAssert.assertThat(messages, Matchers.containsInAnyOrder(message1, message2, message3)); - } - - - @Test - public void generatedJavaFileObjectChecks_addAndGet() { - - unit.addGeneratedJavaFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, generatedJavaFileObjectChecks3.getLocation(), generatedJavaFileObjectChecks3.getClassName(), generatedJavaFileObjectChecks3.getKind(), generatedJavaFileObjectChecks3.getGeneratedFileObjectMatcher()); - unit.addGeneratedJavaFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, generatedJavaFileObjectChecks4.getLocation(), generatedJavaFileObjectChecks4.getClassName(), generatedJavaFileObjectChecks4.getKind(), generatedJavaFileObjectChecks4.getGeneratedFileObjectMatcher()); - - - // do assertion - assertGeneratedJavaFileObjectChecks(unit); - } - - private void assertGeneratedJavaFileObjectChecks(CompileTestConfiguration configuration) { - MatcherAssert.assertThat(configuration.getGeneratedJavaFileObjectChecks(), Matchers.containsInAnyOrder(generatedJavaFileObjectChecks3, generatedJavaFileObjectChecks4)); - } - - - @Test - public void generatedFileObjectChecks_addAndGet() { - - unit.addGeneratedFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, generatedFileObjectChecks3.getLocation(), generatedFileObjectChecks3.getPackageName(), generatedFileObjectChecks3.getRelativeName(), generatedFileObjectChecks3.getGeneratedFileObjectMatchers()); - unit.addGeneratedFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, generatedFileObjectChecks4.getLocation(), generatedFileObjectChecks4.getPackageName(), generatedFileObjectChecks4.getRelativeName(), generatedFileObjectChecks4.getGeneratedFileObjectMatchers()); - - - // do assertion - assertGeneratedFileObjectChecks(unit); - } - - private void assertGeneratedFileObjectChecks(CompileTestConfiguration configuration) { - MatcherAssert.assertThat(configuration.getGeneratedFileObjectChecks(), Matchers.containsInAnyOrder(generatedFileObjectChecks3, generatedFileObjectChecks4)); - } - - @Test - public void passInConfigurationChecks_addAndGet() { - - unit.setPassInConfiguration(CompileTestConfigurationTest.class, TestAnnotation.class); - - // do assertion - assertPassInConfiguration(unit, CompileTestConfigurationTest.class, TestAnnotation.class); - } - - private void assertPassInConfiguration(CompileTestConfiguration configuration, Class passedInClass, Class annotationToScanFor) { - MatcherAssert.assertThat(configuration.getPassInConfiguration().getPassedInClass(), Matchers.is(passedInClass)); - MatcherAssert.assertThat(configuration.getPassInConfiguration().getAnnotationToScanFor(), Matchers.is(annotationToScanFor)); - } - - @Test - public void useModulesChecks() { - unit.addModules("A", "B", "C"); - unit.addModules("D"); - - - // do assertion - MatcherAssert.assertThat(unit.getModules(), Matchers.containsInAnyOrder("A", "B", "C", "D")); - } - - - @Test - public void cloneConfiguration_cloneConfiguration() { - - sourceFiles_addAndGet(); - processors_addAndGet(); - processorTypes_addAndGet(); - processorsWithExpectedExceptions_addAndGet(); - expectedThrownException_setAndGet(); - compilerMessageCheck_setAndGet(); - generatedJavaFileObjectChecks_addAndGet(); - generatedFileObjectChecks_addAndGet(); - modules_addAndGet(); - - CompileTestConfiguration clonedConfiguration = CompileTestConfiguration.cloneConfiguration(unit); - - assertSourceFiles(clonedConfiguration); - assertProcessors(clonedConfiguration); - assertProcessorTypes(clonedConfiguration); - assertProcessorsWithExpectedExceptions(clonedConfiguration); - assertExpectedThrownException(clonedConfiguration, expectedThrownException); - assertMessages(clonedConfiguration.getCompilerMessageChecks()); - assertGeneratedJavaFileObjectChecks(clonedConfiguration); - assertGeneratedFileObjectChecks(clonedConfiguration); - assertModules(clonedConfiguration); - - } - - - @Test - public void wrappedProcessorCacheIsResetCorrectly_addProcessors() { - - processorTypes_addAndGet(); - - Set previousCache = unit.getWrappedProcessors(); - - processors_addAndGet(); - - Set currentCache = unit.getWrappedProcessors(); - MatcherAssert.assertThat("Cache instances must not match!!!", currentCache != previousCache); - - - } - - @Test - public void wrappedProcessorCacheIsResetCorrectly_addProcessorsTypes() { - processors_addAndGet(); - - Set previousCache = unit.getWrappedProcessors(); - - processorTypes_addAndGet(); - - Set currentCache = unit.getWrappedProcessors(); - MatcherAssert.assertThat("Cache instances must not match!!!", currentCache != previousCache); - - } - - @Test - public void wrappedProcessorCacheIsResetCorrectly_addProcessorsTypesWithExpectedExceptions() { - processors_addAndGet(); - - Set previousCache = unit.getWrappedProcessors(); - - processorsWithExpectedExceptions_addAndGet(); - - Set currentCache = unit.getWrappedProcessors(); - MatcherAssert.assertThat("Cache instances must not match!!!", currentCache != previousCache); - - } - - @Test - public void wrappedProcessorCacheSubsequentCallsShouldReturnSameCache() { - processors_addAndGet(); - - Set previousCache = unit.getWrappedProcessors(); - Set currentCache = unit.getWrappedProcessors(); - - MatcherAssert.assertThat("Subsequent calls to get wrapped processors should return same cache set!!!", currentCache == previousCache); - - } - - @Test - public void wrappedModulesCacheIsResetCorrectly_addProcessors() { - - processorTypes_addAndGet(); - - Set previousCache = unit.getWrappedProcessors(); - - processors_addAndGet(); - - Set currentCache = unit.getWrappedProcessors(); - MatcherAssert.assertThat("Cache instances must not match!!!", currentCache != previousCache); - - - } - - - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - // -- STATIC INNER CLASSES TESTS - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - - - // ------------------------------------------------------------------- - // -- ProcessorWithExpectedException - // ------------------------------------------------------------------- - - @Test - public void processorWithExpectedException_matching() { - - CompileTestConfiguration.ProcessorWithExpectedException unit = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, IllegalStateException.class); - CompileTestConfiguration.ProcessorWithExpectedException otherObj = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, IllegalStateException.class); - - MatcherAssert.assertThat("Objects should be detected as equal", unit.equals(otherObj)); - MatcherAssert.assertThat("Objects should be detected as equal", otherObj.equals(unit)); - - MatcherAssert.assertThat("HashCodes should be identical", unit.hashCode() == otherObj.hashCode()); - - } - - @Test - public void processorWithExpectedException_matching_processorIsNull() { - - CompileTestConfiguration.ProcessorWithExpectedException unit = new CompileTestConfiguration.ProcessorWithExpectedException(null, IllegalStateException.class); - CompileTestConfiguration.ProcessorWithExpectedException otherObj = new CompileTestConfiguration.ProcessorWithExpectedException(null, IllegalStateException.class); - - MatcherAssert.assertThat("Objects should be detected as equal", unit.equals(otherObj)); - MatcherAssert.assertThat("Objects should be detected as equal", otherObj.equals(unit)); - - MatcherAssert.assertThat("HashCodes should be identical", unit.hashCode() == otherObj.hashCode()); - - } - - @Test - public void processorWithExpectedException_matching_throwableIsNull() { - - CompileTestConfiguration.ProcessorWithExpectedException unit = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, null); - CompileTestConfiguration.ProcessorWithExpectedException otherObj = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, null); - - MatcherAssert.assertThat("Objects should be detected as equal", unit.equals(otherObj)); - MatcherAssert.assertThat("Objects should be detected as equal", otherObj.equals(unit)); - - MatcherAssert.assertThat("HashCodes should be identical", unit.hashCode() == otherObj.hashCode()); - - } - - @Test - public void processorWithExpectedException_matching_allParametersAreNull() { - - CompileTestConfiguration.ProcessorWithExpectedException unit = new CompileTestConfiguration.ProcessorWithExpectedException(null, null); - CompileTestConfiguration.ProcessorWithExpectedException otherObj = new CompileTestConfiguration.ProcessorWithExpectedException(null, null); - - MatcherAssert.assertThat("Objects should be detected as equal", unit.equals(otherObj)); - MatcherAssert.assertThat("Objects should be detected as equal", otherObj.equals(unit)); - - MatcherAssert.assertThat("HashCodes should be identical", unit.hashCode() == otherObj.hashCode()); - - } - - @Test - public void processorWithExpectedException_nonMatching_passedObjectIsNull() { - - CompileTestConfiguration.ProcessorWithExpectedException unit = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, IllegalStateException.class); - - MatcherAssert.assertThat("Objects should be detected as not equal", !unit.equals(null)); - - - } - - @Test - public void processorWithExpectedException_nonMatching_oneProcessorIsNull() { - - CompileTestConfiguration.ProcessorWithExpectedException unit = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, IllegalStateException.class); - CompileTestConfiguration.ProcessorWithExpectedException otherObj = new CompileTestConfiguration.ProcessorWithExpectedException(null, IllegalStateException.class); - - MatcherAssert.assertThat("Objects should not be detected as equal", !unit.equals(otherObj)); - MatcherAssert.assertThat("Objects should not be detected as equal", !otherObj.equals(unit)); - - - } - - @Test - public void processorWithExpectedException_nonMatching_oneThrowableIsNull() { - - CompileTestConfiguration.ProcessorWithExpectedException unit = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, IllegalStateException.class); - CompileTestConfiguration.ProcessorWithExpectedException otherObj = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, null); - - MatcherAssert.assertThat("Objects should not be detected as equal", !unit.equals(otherObj)); - MatcherAssert.assertThat("Objects should not be detected as equal", !otherObj.equals(unit)); - - - } - - @Test - public void processorWithExpectedException_nonMatching_processorIsDifferent() { - - CompileTestConfiguration.ProcessorWithExpectedException unit = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, IllegalStateException.class); - CompileTestConfiguration.ProcessorWithExpectedException otherObj = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor2.class, IllegalStateException.class); - - MatcherAssert.assertThat("Objects should not be detected as equal", !unit.equals(otherObj)); - MatcherAssert.assertThat("Objects should not be detected as equal", !otherObj.equals(unit)); - - - } - - @Test - public void processorWithExpectedException_nonMatching_throwableIsDifferent() { - - CompileTestConfiguration.ProcessorWithExpectedException unit = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, IllegalStateException.class); - CompileTestConfiguration.ProcessorWithExpectedException otherObj = new CompileTestConfiguration.ProcessorWithExpectedException(SimpleTestProcessor1.class, IllegalArgumentException.class); - - MatcherAssert.assertThat("Objects should not be detected as equal", !unit.equals(otherObj)); - MatcherAssert.assertThat("Objects should not be detected as equal", !otherObj.equals(unit)); - - - } - - - // ------------------------------------------------------------------- - // -- GeneratedFileObjectCheck - // ------------------------------------------------------------------- - - - @Test - public void generatedFileObjectCheck_matching_withFileObject() { - - CompileTestConfiguration.GeneratedFileObjectCheck otherObj = new CompileTestConfiguration.GeneratedFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, generatedFileObjectChecks3.getLocation(), - generatedFileObjectChecks3.getPackageName(), generatedFileObjectChecks3.getRelativeName(), generatedFileObjectChecks3.getGeneratedFileObjectMatchers()); - - MatcherAssert.assertThat("Objects should be detected as equal", generatedFileObjectChecks3.equals(otherObj)); - MatcherAssert.assertThat("Objects should be detected as equal", otherObj.equals(generatedFileObjectChecks3)); - - MatcherAssert.assertThat("HashCodes should be identical", generatedFileObjectChecks3.hashCode() == otherObj.hashCode()); - - } - - @Test - public void generatedFileObjectCheck_notMatching() { - - - MatcherAssert.assertThat("Objects should not be detected as equal", !generatedFileObjectChecks3.equals(generatedFileObjectChecks4)); - - MatcherAssert.assertThat("Objects should not be detected as equal", !generatedFileObjectChecks4.equals(generatedFileObjectChecks3)); - - } - - @Test - public void generatedFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher() { - - // location differs - JavaFileManager.Location alternativeLocation = StandardLocation.SOURCE_PATH; - MatcherAssert.assertThat("PRECONDITION locations must not match", alternativeLocation != generatedFileObjectChecks3.getLocation()); - generatedFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher_singleTest(generatedFileObjectChecks3, alternativeLocation, - generatedFileObjectChecks3.getPackageName(), generatedFileObjectChecks3.getRelativeName(), generatedFileObjectChecks3.getGeneratedFileObjectMatchers()); - - // packageName differs - String alternativePackageName = "XXX"; - MatcherAssert.assertThat("PRECONDITION locations must not match", !alternativePackageName.equals(generatedFileObjectChecks3.getPackageName())); - generatedFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher_singleTest(generatedFileObjectChecks3, generatedFileObjectChecks3.getLocation(), - alternativePackageName, generatedFileObjectChecks3.getRelativeName(), generatedFileObjectChecks3.getGeneratedFileObjectMatchers()); - - // relativeName differs - String alternativeRelativeName = "XXX"; - MatcherAssert.assertThat("PRECONDITION locations must not match", !alternativeRelativeName.equals(generatedFileObjectChecks3.getRelativeName())); - generatedFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher_singleTest(generatedFileObjectChecks3, generatedFileObjectChecks3.getLocation(), - generatedFileObjectChecks3.getPackageName(), alternativeRelativeName, generatedFileObjectChecks3.getGeneratedFileObjectMatchers()); - - // expectedFileObject differs - generatedFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher_singleTest(generatedFileObjectChecks3, generatedFileObjectChecks3.getLocation(), - generatedFileObjectChecks3.getPackageName(), generatedFileObjectChecks3.getRelativeName(), toArray(Mockito.mock(GeneratedFileObjectMatcher.class))); - - } - - private void generatedFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher_singleTest(CompileTestConfiguration.GeneratedFileObjectCheck unit, JavaFileManager.Location location, String packageName, String relativeName, GeneratedFileObjectMatcher[] generatedFileObjectMatcher) { - - CompileTestConfiguration.GeneratedFileObjectCheck otherObj = new CompileTestConfiguration.GeneratedFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, location, - packageName, packageName, generatedFileObjectMatcher); - - MatcherAssert.assertThat("Objects should not be detected as equal", !unit.equals(otherObj)); - MatcherAssert.assertThat("Objects should not be detected as equal", !otherObj.equals(unit)); - - } - - // ------------------------------------------------------------------- - // -- GeneratedJavaFileObjectCheck - // ------------------------------------------------------------------- - - - @Test - public void generatedJavaFileObjectCheck_notMatching() { - - - MatcherAssert.assertThat("Objects should not be detected as equal", !generatedJavaFileObjectChecks3.equals(generatedJavaFileObjectChecks4)); - MatcherAssert.assertThat("Objects should not be detected as equal", !generatedJavaFileObjectChecks4.equals(generatedJavaFileObjectChecks3)); - - } - - - @Test - public void generatedJavaFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher() { - - // location differs - JavaFileManager.Location alternativeLocation = StandardLocation.SOURCE_PATH; - MatcherAssert.assertThat("PRECONDITION locations must not match", alternativeLocation != generatedJavaFileObjectChecks3.getLocation()); - generatedJavaFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher_singleTest(generatedJavaFileObjectChecks3, alternativeLocation, - generatedJavaFileObjectChecks3.getClassName(), generatedJavaFileObjectChecks3.getKind(), Mockito.mock(GeneratedFileObjectMatcher.class)); - - // className differs - String alternativeClassName = "XXX"; - MatcherAssert.assertThat("PRECONDITION locations must not match", !alternativeClassName.equals(generatedJavaFileObjectChecks3.getClassName())); - generatedJavaFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher_singleTest(generatedJavaFileObjectChecks3, generatedJavaFileObjectChecks3.getLocation(), - alternativeClassName, generatedJavaFileObjectChecks3.getKind(), Mockito.mock(GeneratedFileObjectMatcher.class)); - - // kind differs - JavaFileObject.Kind alternativeKind = JavaFileObject.Kind.OTHER; - MatcherAssert.assertThat("PRECONDITION locations must not match", !alternativeKind.equals(generatedJavaFileObjectChecks3.getKind())); - generatedJavaFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher_singleTest(generatedJavaFileObjectChecks3, generatedJavaFileObjectChecks3.getLocation(), - generatedJavaFileObjectChecks3.getClassName(), alternativeKind, Mockito.mock(GeneratedFileObjectMatcher.class)); - - // expectedFileObject differs - generatedJavaFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher_singleTest(generatedJavaFileObjectChecks3, generatedJavaFileObjectChecks3.getLocation(), - generatedJavaFileObjectChecks3.getClassName(), generatedJavaFileObjectChecks3.getKind(), Mockito.mock(GeneratedFileObjectMatcher.class)); - - } - - private void generatedJavaFileObjectCheck_notMatchingSingleField_withGeneratedFileObjectMatcher_singleTest(CompileTestConfiguration.GeneratedJavaFileObjectCheck unit, JavaFileManager.Location location, String className, JavaFileObject.Kind kind, GeneratedFileObjectMatcher generatedFileObjectMatcher) { - - CompileTestConfiguration.GeneratedJavaFileObjectCheck otherObj = new CompileTestConfiguration.GeneratedJavaFileObjectCheck(CompileTestConfiguration.FileObjectCheckType.EXISTS, location, - className, kind, generatedFileObjectMatcher); - - MatcherAssert.assertThat("Objects should not be detected as equal", !unit.equals(otherObj)); - MatcherAssert.assertThat("Objects should not be detected as equal", !otherObj.equals(unit)); - - } - - -} diff --git a/cute/src/test/java/io/toolisticon/cute/impl/CompilerMessageCheckTest.java b/cute/src/test/java/io/toolisticon/cute/impl/CompilerMessageCheckTest.java deleted file mode 100644 index 1abb91e..0000000 --- a/cute/src/test/java/io/toolisticon/cute/impl/CompilerMessageCheckTest.java +++ /dev/null @@ -1,110 +0,0 @@ -package io.toolisticon.cute.impl; - -import io.toolisticon.cute.CompileTestBuilder; -import io.toolisticon.cute.UnitTest; -import org.junit.Test; - -import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; - -/** - * Unit Test for checking correctness of compiler messages checks. - */ -public class CompilerMessageCheckTest { - - CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder.unitTest(); - - @Test - public void testComplexCompilerMessageCheck_findMessage_withAll() { - - builder.compilationShouldSucceed().defineTest(new UnitTest() { - @Override - public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { - processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); - } - }) - .expectWarningMessage().atSource("/AnnotationProcessorUnitTestClass.java").atLineNumber(13L).atColumnNumber(8L).thatIsEqualTo("ABC") - - .executeTest(); - - } - - @Test(expected = AssertionError.class) - public void testComplexCompilerMessageCheck_dontFindMessage_withAll_wrongSource() { - - builder.compilationShouldSucceed().defineTest(new UnitTest() { - @Override - public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { - processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); - } - }) - .expectWarningMessage().atSource("/XYZ.java").atLineNumber(13L).atColumnNumber(8L).thatIsEqualTo("ABC") - - .executeTest(); - - } - - @Test(expected = AssertionError.class) - public void testComplexCompilerMessageCheck_dontFindMessage_withAll_wrongLine() { - - builder.compilationShouldSucceed().defineTest(new UnitTest() { - @Override - public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { - processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); - } - }) - .expectWarningMessage().atSource("/AnnotationProcessorUnitTestClass.java").atLineNumber(3L).atColumnNumber(8L).thatIsEqualTo("ABC") - - .executeTest(); - - } - - @Test(expected = AssertionError.class) - public void testComplexCompilerMessageCheck_dontFindMessage_withAll_wrongColumn() { - - builder.compilationShouldSucceed().defineTest(new UnitTest() { - @Override - public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { - processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); - } - }) - .expectWarningMessage().atSource("/AnnotationProcessorUnitTestClass.java").atLineNumber(13L).atColumnNumber(7L).thatIsEqualTo("ABC") - - .executeTest(); - - } - - @Test(expected = AssertionError.class) - public void testComplexCompilerMessageCheck_dontFindMessage_withAll_wrongMessage() { - - builder.compilationShouldSucceed().defineTest(new UnitTest() { - @Override - public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { - processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); - } - }) - .expectWarningMessage().atSource("/AnnotationProcessorUnitTestClass.java").atLineNumber(13L).atColumnNumber(8L).thatIsEqualTo("BC") - - .executeTest(); - - } - - @Test - public void testComplexCompilerMessageCheck_findMessageSubstring_withAll() { - - builder.compilationShouldSucceed().defineTest(new UnitTest() { - @Override - public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { - processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "ABC", element); - } - }) - .expectWarningMessage().atSource("/AnnotationProcessorUnitTestClass.java").atLineNumber(13L).atColumnNumber(8L).thatContains("BC") - - .executeTest(); - - } - - - -} diff --git a/cute/src/test/java/io/toolisticon/cute/integrationtest/CompiledClassesAndGeneratedFilesTest.java b/cute/src/test/java/io/toolisticon/cute/integrationtest/CompiledClassesAndGeneratedFilesTest.java index 2b94d64..0330abe 100644 --- a/cute/src/test/java/io/toolisticon/cute/integrationtest/CompiledClassesAndGeneratedFilesTest.java +++ b/cute/src/test/java/io/toolisticon/cute/integrationtest/CompiledClassesAndGeneratedFilesTest.java @@ -1,7 +1,7 @@ package io.toolisticon.cute.integrationtest; -import io.toolisticon.cute.CompileTestBuilder; import io.toolisticon.cute.Constants; +import io.toolisticon.cute.Cute; import io.toolisticon.cute.GeneratedFileObjectMatcher; import io.toolisticon.cute.JavaFileObjectUtils; import io.toolisticon.cute.TestUtilities; @@ -27,11 +27,12 @@ public class CompiledClassesAndGeneratedFilesTest { @Test public void testCompiledClassesExist() { - CompileTestBuilder.compilationTest() - .addProcessors(SimpleTestProcessor1.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatJavaFileObjectExists(StandardLocation.CLASS_OUTPUT, "io.toolisticon.cute.integrationtest.CompiledClassesAndGeneratedFilesExistTestcase", JavaFileObject.Kind.CLASS) + Cute.blackBoxTest() + .given().processors(SimpleTestProcessor1.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled() + .thenExpectThat().compilationSucceeds() + .andThat().javaFileObject(StandardLocation.CLASS_OUTPUT, "io.toolisticon.cute.integrationtest.CompiledClassesAndGeneratedFilesExistTestcase", JavaFileObject.Kind.CLASS).exists() .executeTest(); @@ -76,11 +77,12 @@ public void testCompiledResourceExistButShouldnt() { boolean assertionErrorWasThrown = false; try { - CompileTestBuilder.compilationTest() - .addProcessors(FileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatFileObjectDoesntExist(StandardLocation.SOURCE_OUTPUT, "/META-INF", "jupp.txt") + Cute.blackBoxTest() + .given().processors(FileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled() + .thenExpectThat().compilationSucceeds() + .andThat().fileObject(StandardLocation.SOURCE_OUTPUT, "/META-INF", "jupp.txt").doesntExist() .executeTest(); } catch (AssertionError e) { @@ -97,11 +99,12 @@ public void testCompiledResourceExistButShouldnt() { @Test public void testCompiledResourceExist_byFileObject() { - CompileTestBuilder.compilationTest() - .addProcessors(FileGeneratorProcessor.class) - .addSources("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java") - .compilationShouldSucceed() - .expectThatFileObjectExists(StandardLocation.SOURCE_OUTPUT, "/META-INF", "jupp.txt", JavaFileObjectUtils.readFromString("XXX")) + Cute.blackBoxTest() + .given().processors(FileGeneratorProcessor.class) + .andSourceFiles("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java") + .whenCompiled() + .thenExpectThat().compilationSucceeds() + .andThat().fileObject(StandardLocation.SOURCE_OUTPUT, "/META-INF", "jupp.txt").equals( JavaFileObjectUtils.readFromString("XXX")) .executeTest(); @@ -110,11 +113,12 @@ public void testCompiledResourceExist_byFileObject() { @Test public void testCompiledResourceExist_ByMatcher() { - CompileTestBuilder.compilationTest() - .addProcessors(FileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatFileObjectExists(StandardLocation.SOURCE_OUTPUT, "/META-INF", "jupp.txt", new GeneratedFileObjectMatcher() { + Cute.blackBoxTest() + .given().processors(FileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled() + .thenExpectThat().compilationSucceeds() + .andThat().fileObject(StandardLocation.SOURCE_OUTPUT, "/META-INF", "jupp.txt").matches( new GeneratedFileObjectMatcher() { @Override public boolean check(FileObject fileObject) throws IOException { return true; @@ -131,11 +135,12 @@ public void testCompiledResourceNotExistButShould_byFileObject() { boolean assertionErrorWasThrown = false; try { - CompileTestBuilder.compilationTest() - .addProcessors(FileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatFileObjectExists(StandardLocation.SOURCE_OUTPUT, "/META-INF", "jupp.txt", JavaFileObjectUtils.readFromString("XXX!!!")) + Cute.blackBoxTest() + .given().processors(FileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled() + .thenExpectThat().compilationSucceeds() + .andThat().fileObject(StandardLocation.SOURCE_OUTPUT, "/META-INF", "jupp.txt").equals(JavaFileObjectUtils.readFromString("XXX!!!")) .executeTest(); } catch (AssertionError e) { @@ -154,11 +159,11 @@ public void testCompiledResourceNotExistButShould_byMatcher() { boolean assertionErrorWasThrown = false; try { - CompileTestBuilder.compilationTest() - .addProcessors(FileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatFileObjectExists(StandardLocation.SOURCE_OUTPUT, "/META-INF", "jupp.txt", new GeneratedFileObjectMatcher() { + Cute.blackBoxTest() + .given().processors(FileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled().thenExpectThat().compilationSucceeds() + .andThat().fileObject(StandardLocation.SOURCE_OUTPUT, "/META-INF", "jupp.txt").matches( new GeneratedFileObjectMatcher() { @Override public boolean check(FileObject fileObject) throws IOException { return false; @@ -215,12 +220,12 @@ public boolean process(Set annotations, RoundEnvironment @Test public void testCompiledJavaFileObjectExist() { - CompileTestBuilder.compilationTest() - .addProcessors(JavaFileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatJavaFileObjectExists(StandardLocation.SOURCE_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME, JavaFileObject.Kind.SOURCE) - .expectThatJavaFileObjectExists(StandardLocation.CLASS_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME, JavaFileObject.Kind.CLASS) + Cute.blackBoxTest() + .given().processors(JavaFileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled().thenExpectThat().compilationSucceeds() + .andThat().javaFileObject(StandardLocation.SOURCE_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME, JavaFileObject.Kind.SOURCE).exists() + .andThat().javaFileObject(StandardLocation.CLASS_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME, JavaFileObject.Kind.CLASS).exists() .executeTest(); @@ -233,11 +238,11 @@ public void testCompiledJavaFileObjectNotExistButShould_byJavaFileObject() { boolean assertionErrorWasThrown = false; try { - CompileTestBuilder.compilationTest() - .addProcessors(JavaFileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatJavaFileObjectExists(StandardLocation.SOURCE_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + ".Murks", JavaFileObject.Kind.SOURCE) + Cute.blackBoxTest() + .given().processors(JavaFileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled().thenExpectThat().compilationSucceeds() + .andThat().javaFileObject(StandardLocation.SOURCE_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + ".Murks", JavaFileObject.Kind.SOURCE).exists() .executeTest(); } catch (AssertionError e) { @@ -257,11 +262,12 @@ public void testCompiledJavaFileObjectNotExistButShould_bySource() { boolean assertionErrorWasThrown = false; try { - CompileTestBuilder.compilationTest() - .addProcessors(JavaFileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatGeneratedSourceFileExists(JavaFileGeneratorProcessor.PACKAGE_NAME + ".Murks") + Cute.blackBoxTest() + .given().processors(JavaFileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled() + .thenExpectThat().compilationSucceeds() + .andThat().generatedSourceFile(JavaFileGeneratorProcessor.PACKAGE_NAME + ".Murks").exists() .executeTest(); } catch (AssertionError e) { @@ -281,11 +287,12 @@ public void testCompiledJavaFileObjectExistButShouldnt_byJavaFileObject() { boolean assertionErrorWasThrown = false; try { - CompileTestBuilder.compilationTest() - .addProcessors(JavaFileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatJavaFileObjectDoesntExist(StandardLocation.SOURCE_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME, JavaFileObject.Kind.SOURCE) + Cute.blackBoxTest() + .given().processors(JavaFileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled() + .thenExpectThat().compilationSucceeds() + .andThat().javaFileObject(StandardLocation.SOURCE_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME, JavaFileObject.Kind.SOURCE).doesntExist() .executeTest(); } catch (AssertionError e) { @@ -305,11 +312,12 @@ public void testCompiledJavaFileObjectExistButShouldnt_bySource() { boolean assertionErrorWasThrown = false; try { - CompileTestBuilder.compilationTest() - .addProcessors(JavaFileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatGeneratedSourceFileDoesntExist(JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME) + Cute.blackBoxTest() + .given().processors(JavaFileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled() + .thenExpectThat().compilationSucceeds() + .andThat().generatedSourceFile(JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME).doesntExist() .executeTest(); } catch (AssertionError e) { @@ -329,11 +337,12 @@ public void testCompiledJavaFileObjectNotExist_byJavaFileObjectComparision() { boolean assertionErrorWasThrown = false; try { - CompileTestBuilder.compilationTest() - .addProcessors(JavaFileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatJavaFileObjectExists(StandardLocation.SOURCE_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME, JavaFileObject.Kind.SOURCE, JavaFileObjectUtils.readFromString("XXX!!")) + Cute.blackBoxTest() + .given().processors(JavaFileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled() + .thenExpectThat().compilationSucceeds() + .andThat().javaFileObject(StandardLocation.SOURCE_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME, JavaFileObject.Kind.SOURCE).equals(JavaFileObjectUtils.readFromString("XXX!!")) .executeTest(); } catch (AssertionError e) { @@ -353,11 +362,11 @@ public void testCompiledJavaFileObjectNotExist_byMatcher() { boolean assertionErrorWasThrown = false; try { - CompileTestBuilder.compilationTest() - .addProcessors(JavaFileGeneratorProcessor.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) - .compilationShouldSucceed() - .expectThatJavaFileObjectExists(StandardLocation.SOURCE_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME, JavaFileObject.Kind.SOURCE, new GeneratedFileObjectMatcher() { + Cute.blackBoxTest() + .given().processors(JavaFileGeneratorProcessor.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/CompiledClassesAndGeneratedFilesExistTestcase.java")) + .whenCompiled().thenExpectThat().compilationSucceeds() + .andThat().javaFileObject(StandardLocation.SOURCE_OUTPUT, JavaFileGeneratorProcessor.PACKAGE_NAME + "." + JavaFileGeneratorProcessor.CLASS_NAME, JavaFileObject.Kind.SOURCE).matches( new GeneratedFileObjectMatcher() { @Override public boolean check(FileObject fileObject) throws IOException { return false; diff --git a/cute/src/test/java/io/toolisticon/cute/integrationtest/ProcessorWasAppliedTest.java b/cute/src/test/java/io/toolisticon/cute/integrationtest/ProcessorWasAppliedTest.java index 6903f73..fce8c7b 100644 --- a/cute/src/test/java/io/toolisticon/cute/integrationtest/ProcessorWasAppliedTest.java +++ b/cute/src/test/java/io/toolisticon/cute/integrationtest/ProcessorWasAppliedTest.java @@ -1,6 +1,6 @@ package io.toolisticon.cute.integrationtest; -import io.toolisticon.cute.CompileTestBuilder; +import io.toolisticon.cute.Cute; import io.toolisticon.cute.JavaFileObjectUtils; import io.toolisticon.cute.common.SimpleTestProcessor1; import io.toolisticon.cute.common.SimpleTestProcessor2; @@ -16,10 +16,11 @@ public class ProcessorWasAppliedTest { @Test public void concreteProcessorClassInstance_wasApplied() { - CompileTestBuilder - .unitTest() - .useProcessor(new SimpleTestProcessor1()) - .useSource(JavaFileObjectUtils.readFromResource("/integrationtest/AnnotationProcessorAppliedTestClass.java")) + Cute.blackBoxTest() + .given().processors( SimpleTestProcessor1.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/AnnotationProcessorAppliedTestClass.java")) + .whenCompiled() + .thenExpectThat().compilationSucceeds() .executeTest(); @@ -29,10 +30,9 @@ public void concreteProcessorClassInstance_wasApplied() { public void concreteProcessorClassInstance_wasNotApplied() { boolean assertionErrorWasTriggered = false; try { - CompileTestBuilder - .unitTest() - .useProcessor(new SimpleTestProcessor2()) - .useSource(JavaFileObjectUtils.readFromResource("/integrationtest/AnnotationProcessorAppliedTestClass.java")) + Cute.blackBoxTest() + .given().processors( SimpleTestProcessor2.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/AnnotationProcessorAppliedTestClass.java")) .executeTest(); } catch (AssertionError e) { @@ -46,9 +46,10 @@ public void concreteProcessorClassInstance_wasNotApplied() { } + /*- @Test public void anonymousProcessorClassInstanceOfProcessor_wasApplied() { - CompileTestBuilder + CuteFluentApiStarter.unitTest() .unitTest() .useProcessor(new SimpleTestProcessor1() { }) @@ -79,13 +80,14 @@ public void anonymousProcessorClassInstanceOfProcessor_wasNotApplied() { } + */ + @Test public void anonymousProcessorClassInstanceOfClass_wasApplied() { - CompileTestBuilder - .compilationTest() - .addProcessors(SimpleTestProcessor1.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/AnnotationProcessorAppliedTestClass.java")) + Cute.blackBoxTest() + .given().processors(SimpleTestProcessor1.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/AnnotationProcessorAppliedTestClass.java")) .executeTest(); } @@ -96,10 +98,9 @@ public void anonymousProcessorClassInstanceOfClass_wasNotApplied() { boolean assertionErrorWasTriggered = false; try { - CompileTestBuilder - .compilationTest() - .addProcessors(SimpleTestProcessor2.class) - .addSources(JavaFileObjectUtils.readFromResource("/integrationtest/AnnotationProcessorAppliedTestClass.java")) + Cute.blackBoxTest() + .given().processors(SimpleTestProcessor2.class) + .andSourceFiles(JavaFileObjectUtils.readFromResource("/integrationtest/AnnotationProcessorAppliedTestClass.java")) .executeTest(); } catch (AssertionError e) { diff --git a/cute/src/test/java/io/toolisticon/cute/matchers/ContainsStringsGeneratedFileObjectMatcherTest.java b/cute/src/test/java/io/toolisticon/cute/matchers/ContainsStringsGeneratedFileObjectMatcherTest.java index ffb7060..bdd99b7 100644 --- a/cute/src/test/java/io/toolisticon/cute/matchers/ContainsStringsGeneratedFileObjectMatcherTest.java +++ b/cute/src/test/java/io/toolisticon/cute/matchers/ContainsStringsGeneratedFileObjectMatcherTest.java @@ -1,12 +1,9 @@ package io.toolisticon.cute.matchers; -import io.toolisticon.cute.CompileTestBuilder; import io.toolisticon.cute.FailingAssertionException; import io.toolisticon.cute.JavaFileObjectUtils; import org.junit.Test; -import javax.tools.JavaFileObject; -import javax.tools.StandardLocation; import java.io.IOException; /** @@ -28,12 +25,15 @@ public void testForContainingStrings_invalid() throws IOException { } + /*- @Test public void checkUsageOnFileObject() { - CompileTestBuilder.compilationTest().expectThatJavaFileObjectExists(StandardLocation.SOURCE_OUTPUT,"io.toolisticon.cute.TestClass", JavaFileObject.Kind.SOURCE,CoreGeneratedFileObjectMatchers.createContainsSubstringsMatcher("abc")); + CuteFluentApiStarter.blackBoxTest()..compilationTest().expectThatJavaFileObjectExists(StandardLocation.SOURCE_OUTPUT,"io.toolisticon.cute.TestClass", JavaFileObject.Kind.SOURCE,CoreGeneratedFileObjectMatchers.createContainsSubstringsMatcher("abc")); } + */ + } \ No newline at end of file diff --git a/cute/src/test/resources/AnnotationProcessorUnitTestTestClass.java b/cute/src/test/resources/AnnotationProcessorUnitTestTestClass.java new file mode 100644 index 0000000..bd6fc48 --- /dev/null +++ b/cute/src/test/resources/AnnotationProcessorUnitTestTestClass.java @@ -0,0 +1,86 @@ +package io.toolisticon.compiletesting.test; + +import io.toolisticon.cute.PassIn; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +/** + * Test class for annotation processor tools. + */ +@PassIn +public class AnnotationProcessorUnitTestTestClass { + + private String privateField; + protected String protectedField; + String packagePrivateField; + public String publicField; + public final String publicFinalField = ""; + public static String publicStaticField; + public transient String publicTransientField; + + enum TestEnum1 { + TEST11, TEST12; + } + + public enum TestEnum2 { + TEST21, TEST22; + } + + public static class EmbeddedStaticClass { + + } + + public Comparator comparatorWithAnonymousClass = new Comparator() { + @Override + public int compare(Long o1, Long o2) { + return 0; + } + }; + + + public class EmbeddedClass { + + } + + public class EmbeddedClassWithNoNoargConstructor { + + public EmbeddedClassWithNoNoargConstructor(String abs) { + + } + + } + + public abstract class AbstractEmbeddedClass { + + public abstract void abstractMethod(); + + } + + { + int x = 0; + } + + static { + int y = 0; + } + + public AnnotationProcessorUnitTestTestClass() { + + } + + public AnnotationProcessorUnitTestTestClass(String withParameter) { + + } + + public String methodWithReturnTypeAndParameters(Boolean first, String second) { + return ""; + } + + + public int testGenericsOnParameter(Map> o1, Map>> o2) { + return 0; + } + +} diff --git a/cute/src/test/resources/BrokenTestClass.java b/cute/src/test/resources/BrokenTestClass.java new file mode 100644 index 0000000..a712f54 --- /dev/null +++ b/cute/src/test/resources/BrokenTestClass.java @@ -0,0 +1,12 @@ +package io.toolisticon.cute; + +import io.toolisticon.cute.TestAnnotation; + +/** + * Test class for annotation processor tools. + */ +@TestAnnotation +public class BrokenTestClass { + // invalid code => leads to compiler error + sdasdasd +} diff --git a/cute/src/test/resources/TestClass.java b/cute/src/test/resources/TestClass.java index 75bd306..a6bb3fc 100644 --- a/cute/src/test/resources/TestClass.java +++ b/cute/src/test/resources/TestClass.java @@ -1,6 +1,6 @@ package io.toolisticon.cute; -import io.toolisticon.cute.testcases.TestAnnotation; +import io.toolisticon.cute.TestAnnotation; /** * Test class for annotation processor tools. diff --git a/integration-test/java9/namedAutomaticModule/pom.xml b/integration-test/java9/namedAutomaticModule/pom.xml index e405501..e3a182d 100644 --- a/integration-test/java9/namedAutomaticModule/pom.xml +++ b/integration-test/java9/namedAutomaticModule/pom.xml @@ -41,7 +41,7 @@ - integration.test.java9.namedautomaticmodule + integration.test.javanine.namedautomaticmodule diff --git a/integration-test/java9/namedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/java9/namednonmodule/NamedAutomaticModuleTestClass.java b/integration-test/java9/namedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/namednonmodule/NamedAutomaticModuleTestClass.java similarity index 61% rename from integration-test/java9/namedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/java9/namednonmodule/NamedAutomaticModuleTestClass.java rename to integration-test/java9/namedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/namednonmodule/NamedAutomaticModuleTestClass.java index f98487f..ce3fa27 100644 --- a/integration-test/java9/namedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/java9/namednonmodule/NamedAutomaticModuleTestClass.java +++ b/integration-test/java9/namedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/namednonmodule/NamedAutomaticModuleTestClass.java @@ -1,4 +1,4 @@ -package io.toolisticon.cute.integrationtest.java9.namednonmodule; +package io.toolisticon.cute.integrationtest.javanine.namednonmodule; public class NamedAutomaticModuleTestClass { diff --git a/integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/java9/regularmodule/notexported/NotExportedClass.java b/integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/java9/regularmodule/notexported/NotExportedClass.java deleted file mode 100644 index 9404aa0..0000000 --- a/integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/java9/regularmodule/notexported/NotExportedClass.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.toolisticon.cute.integrationtest.java9.regularmodule.notexported; - -public class NotExportedClass { - -} diff --git a/integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/java9/regularmodule/RegularModuleTestClass.java b/integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/regularmodule/RegularModuleTestClass.java similarity index 60% rename from integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/java9/regularmodule/RegularModuleTestClass.java rename to integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/regularmodule/RegularModuleTestClass.java index 920c4e0..58814d5 100644 --- a/integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/java9/regularmodule/RegularModuleTestClass.java +++ b/integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/regularmodule/RegularModuleTestClass.java @@ -1,4 +1,4 @@ -package io.toolisticon.cute.integrationtest.java9.regularmodule; +package io.toolisticon.cute.integrationtest.javanine.regularmodule; public class RegularModuleTestClass { diff --git a/integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/regularmodule/notexported/NotExportedClass.java b/integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/regularmodule/notexported/NotExportedClass.java new file mode 100644 index 0000000..cb71a7b --- /dev/null +++ b/integration-test/java9/regularTestModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/regularmodule/notexported/NotExportedClass.java @@ -0,0 +1,5 @@ +package io.toolisticon.cute.integrationtest.javanine.regularmodule.notexported; + +public class NotExportedClass { + +} diff --git a/integration-test/java9/regularTestModule/src/main/java/module-info.java b/integration-test/java9/regularTestModule/src/main/java/module-info.java index 5ed3b4b..3e34260 100644 --- a/integration-test/java9/regularTestModule/src/main/java/module-info.java +++ b/integration-test/java9/regularTestModule/src/main/java/module-info.java @@ -1,5 +1,5 @@ -module io.toolisticon.cute.integrationtest.java9.regularmodule { +module io.toolisticon.cute.integrationtest.javanine.regularmodule { - exports io.toolisticon.cute.integrationtest.java9.regularmodule; + exports io.toolisticon.cute.integrationtest.javanine.regularmodule; } \ No newline at end of file diff --git a/integration-test/java9/test/src/test/java/io/toolisticon/cute/integrationtest/java9/IntegrationTest.java b/integration-test/java9/test/src/test/java/io/toolisticon/cute/integrationtest/java9/IntegrationTest.java index e809454..69aab22 100644 --- a/integration-test/java9/test/src/test/java/io/toolisticon/cute/integrationtest/java9/IntegrationTest.java +++ b/integration-test/java9/test/src/test/java/io/toolisticon/cute/integrationtest/java9/IntegrationTest.java @@ -1,8 +1,8 @@ package io.toolisticon.cute.integrationtest.java9; -import io.toolisticon.cute.CompileTestBuilder; +import io.toolisticon.cute.Cute; import io.toolisticon.cute.JavaFileObjectUtils; -import io.toolisticon.cute.integrationtest.java9.namednonmodule.NamedAutomaticModuleTestClass; +import io.toolisticon.cute.integrationtest.javanine.namednonmodule.NamedAutomaticModuleTestClass; import org.junit.Test; /** @@ -14,13 +14,14 @@ public class IntegrationTest { @Test public void testBindRegularJavaModule() { - CompileTestBuilder - .compilationTest() - .addSources( - JavaFileObjectUtils.readFromResource("/testcases/bindRegularJavaModule/Test.java"), - JavaFileObjectUtils.readFromResource("/testcases/bindRegularJavaModule/module-info.java")) - .useModules("io.toolisticon.cute.integrationtest.java9.regularmodule") - .compilationShouldSucceed() + Cute + .blackBoxTest() + .given().noProcessors() + .andSourceFiles("/testcases/bindRegularJavaModule/Test.java", + "/testcases/bindRegularJavaModule/module-info.java") + .andUseModules("io.toolisticon.cute.integrationtest.javanine.regularmodule") + .whenCompiled() + .thenExpectThat().compilationSucceeds() .executeTest(); } @@ -29,14 +30,16 @@ public void testBindRegularJavaModule() { @Test public void testBindRegularJavaModule_accessNotExportedClass() { - CompileTestBuilder - .compilationTest() - .addSources( - JavaFileObjectUtils.readFromResource("/testcases/accessNotExportedClass/Test.java"), - JavaFileObjectUtils.readFromResource("/testcases/accessNotExportedClass/module-info.java")) - .useModules("io.toolisticon.cute.integrationtest.java9.regularmodule") - .compilationShouldFail() - .expectErrorMessageThatContains("io.toolisticon.cute.integrationtest.java9.regularmodule.notexported", "is not visible") + Cute + .blackBoxTest() + .given() + .noProcessors() + .andSourceFiles("/testcases/accessNotExportedClass/Test.java","/testcases/accessNotExportedClass/module-info.java") + .andUseModules("io.toolisticon.cute.integrationtest.javanine.regularmodule") + .whenCompiled() + .thenExpectThat() + .compilationFails() + .andThat().compilerMessage().ofKindError().contains("io.toolisticon.cute.integrationtest.javanine.regularmodule.notexported", "is not visible") .executeTest(); } @@ -46,13 +49,15 @@ public void testBindNamedAutomaticJavaModule() { System.out.println("MODULE NAME: " + NamedAutomaticModuleTestClass.class.getModule().getName()); - CompileTestBuilder - .compilationTest() - .addSources( - JavaFileObjectUtils.readFromResource("/testcases/bindNamedAutomaticJavaModule/Test.java"), - JavaFileObjectUtils.readFromResource("/testcases/bindNamedAutomaticJavaModule/module-info.java")) - .useModules("integration.test.java9.namedautomaticmodule") - .compilationShouldSucceed() + Cute + .blackBoxTest() + .given() + .noProcessors() + .andSourceFiles("/testcases/bindNamedAutomaticJavaModule/Test.java","/testcases/bindNamedAutomaticJavaModule/module-info.java") + .andUseModules("integration.test.javanine.namedautomaticmodule") + .whenCompiled() + .thenExpectThat() + .compilationSucceeds() .executeTest(); } @@ -62,13 +67,15 @@ public void testBindUnnamedAutomaticJavaModule() { System.out.println("MODULE NAME: " + NamedAutomaticModuleTestClass.class.getModule().getName()); - CompileTestBuilder - .compilationTest() - .addSources( - JavaFileObjectUtils.readFromResource("/testcases/bindUnnamedAutomaticJavaModule/Test.java"), - JavaFileObjectUtils.readFromResource("/testcases/bindUnnamedAutomaticJavaModule/module-info.java")) - .useModules("integration.test.java9.unnamedautomaticmodule") - .compilationShouldSucceed() + Cute + .blackBoxTest() + .given() + .noProcessors() + .andSourceFiles("/testcases/bindUnnamedAutomaticJavaModule/Test.java","/testcases/bindUnnamedAutomaticJavaModule/module-info.java") + .andUseModules("integration.test.javanine.unnamedautomaticmodule") + .whenCompiled() + .thenExpectThat() + .compilationSucceeds() .executeTest(); } diff --git a/integration-test/java9/test/src/test/resources/testcases/accessNotExportedClass/Test.java b/integration-test/java9/test/src/test/resources/testcases/accessNotExportedClass/Test.java index c98d3b3..79c1cbf 100644 --- a/integration-test/java9/test/src/test/resources/testcases/accessNotExportedClass/Test.java +++ b/integration-test/java9/test/src/test/resources/testcases/accessNotExportedClass/Test.java @@ -1,7 +1,7 @@ -package io.toolisticon.cute.integrationtest.java9; +package io.toolisticon.cute.integrationtest.javanine; -import io.toolisticon.cute.integrationtest.java9.regularmodule.RegularModuleTestClass; -import io.toolisticon.cute.integrationtest.java9.regularmodule.notexported.NotExportedClass; +import io.toolisticon.cute.integrationtest.javanine.regularmodule.RegularModuleTestClass; +import io.toolisticon.cute.integrationtest.javanine.regularmodule.notexported.NotExportedClass; import javax.annotation.processing.Processor; diff --git a/integration-test/java9/test/src/test/resources/testcases/accessNotExportedClass/module-info.java b/integration-test/java9/test/src/test/resources/testcases/accessNotExportedClass/module-info.java index 7d90d7a..056bc57 100644 --- a/integration-test/java9/test/src/test/resources/testcases/accessNotExportedClass/module-info.java +++ b/integration-test/java9/test/src/test/resources/testcases/accessNotExportedClass/module-info.java @@ -1,9 +1,8 @@ - -module io.toolisticon.cute.integrationtest.java9 { +module io.toolisticon.cute.integrationtest.javanine { requires java.compiler; requires java.logging; - requires transitive io.toolisticon.cute.integrationtest.java9.regularmodule; + requires transitive io.toolisticon.cute.integrationtest.javanine.regularmodule; - exports io.toolisticon.cute.integrationtest.java9; + exports io.toolisticon.cute.integrationtest.javanine; } diff --git a/integration-test/java9/test/src/test/resources/testcases/bindNamedAutomaticJavaModule/Test.java b/integration-test/java9/test/src/test/resources/testcases/bindNamedAutomaticJavaModule/Test.java index 12b7b72..3d39b2b 100644 --- a/integration-test/java9/test/src/test/resources/testcases/bindNamedAutomaticJavaModule/Test.java +++ b/integration-test/java9/test/src/test/resources/testcases/bindNamedAutomaticJavaModule/Test.java @@ -1,6 +1,6 @@ -package io.toolisticon.cute.integrationtest.java9; +package io.toolisticon.cute.integrationtest.javanine; -import io.toolisticon.cute.integrationtest.java9.namednonmodule.NamedAutomaticModuleTestClass; +import io.toolisticon.cute.integrationtest.javanine.namednonmodule.NamedAutomaticModuleTestClass; import javax.annotation.processing.Processor; diff --git a/integration-test/java9/test/src/test/resources/testcases/bindNamedAutomaticJavaModule/module-info.java b/integration-test/java9/test/src/test/resources/testcases/bindNamedAutomaticJavaModule/module-info.java index e631200..41f6985 100644 --- a/integration-test/java9/test/src/test/resources/testcases/bindNamedAutomaticJavaModule/module-info.java +++ b/integration-test/java9/test/src/test/resources/testcases/bindNamedAutomaticJavaModule/module-info.java @@ -1,9 +1,8 @@ - -module io.toolisticon.cute.integrationtest.java9 { +module io.toolisticon.cute.integrationtest.javanine { requires java.compiler; requires java.logging; - requires transitive integration.test.java9.namedautomaticmodule; + requires transitive integration.test.javanine.namedautomaticmodule; - exports io.toolisticon.cute.integrationtest.java9; + exports io.toolisticon.cute.integrationtest.javanine; } diff --git a/integration-test/java9/test/src/test/resources/testcases/bindRegularJavaModule/Test.java b/integration-test/java9/test/src/test/resources/testcases/bindRegularJavaModule/Test.java index 336d4f6..5dfa989 100644 --- a/integration-test/java9/test/src/test/resources/testcases/bindRegularJavaModule/Test.java +++ b/integration-test/java9/test/src/test/resources/testcases/bindRegularJavaModule/Test.java @@ -1,6 +1,6 @@ -package io.toolisticon.cute.integrationtest.java9; +package io.toolisticon.cute.integrationtest.javanine; -import io.toolisticon.cute.integrationtest.java9.regularmodule.RegularModuleTestClass; +import io.toolisticon.cute.integrationtest.javanine.regularmodule.RegularModuleTestClass; import javax.annotation.processing.Processor; diff --git a/integration-test/java9/test/src/test/resources/testcases/bindRegularJavaModule/module-info.java b/integration-test/java9/test/src/test/resources/testcases/bindRegularJavaModule/module-info.java index 7d90d7a..056bc57 100644 --- a/integration-test/java9/test/src/test/resources/testcases/bindRegularJavaModule/module-info.java +++ b/integration-test/java9/test/src/test/resources/testcases/bindRegularJavaModule/module-info.java @@ -1,9 +1,8 @@ - -module io.toolisticon.cute.integrationtest.java9 { +module io.toolisticon.cute.integrationtest.javanine { requires java.compiler; requires java.logging; - requires transitive io.toolisticon.cute.integrationtest.java9.regularmodule; + requires transitive io.toolisticon.cute.integrationtest.javanine.regularmodule; - exports io.toolisticon.cute.integrationtest.java9; + exports io.toolisticon.cute.integrationtest.javanine; } diff --git a/integration-test/java9/test/src/test/resources/testcases/bindUnnamedAutomaticJavaModule/Test.java b/integration-test/java9/test/src/test/resources/testcases/bindUnnamedAutomaticJavaModule/Test.java index 32a7fa4..6444e6e 100644 --- a/integration-test/java9/test/src/test/resources/testcases/bindUnnamedAutomaticJavaModule/Test.java +++ b/integration-test/java9/test/src/test/resources/testcases/bindUnnamedAutomaticJavaModule/Test.java @@ -1,6 +1,6 @@ -package io.toolisticon.cute.integrationtest.java9; +package io.toolisticon.cute.integrationtest.javanine; -import io.toolisticon.cute.integrationtest.java9.unnamednonmodule.UnnamedAutomaticModuleTestClass; +import io.toolisticon.cute.integrationtest.javanine.unnamednonmodule.UnnamedAutomaticModuleTestClass; import javax.annotation.processing.Processor; diff --git a/integration-test/java9/test/src/test/resources/testcases/bindUnnamedAutomaticJavaModule/module-info.java b/integration-test/java9/test/src/test/resources/testcases/bindUnnamedAutomaticJavaModule/module-info.java index 12c0c56..a2dcadb 100644 --- a/integration-test/java9/test/src/test/resources/testcases/bindUnnamedAutomaticJavaModule/module-info.java +++ b/integration-test/java9/test/src/test/resources/testcases/bindUnnamedAutomaticJavaModule/module-info.java @@ -1,9 +1,9 @@ -module io.toolisticon.cute.integrationtest.java9 { +module io.toolisticon.cute.integrationtest.javanine { requires java.compiler; requires java.logging; - requires transitive integration.test.java9.unnamedautomaticmodule; + requires transitive integration.test.javanine.unnamedautomaticmodule; - exports io.toolisticon.cute.integrationtest.java9; + exports io.toolisticon.cute.integrationtest.javanine; } diff --git a/integration-test/java9/unnamedAutomaticModule/pom.xml b/integration-test/java9/unnamedAutomaticModule/pom.xml index ef9111e..d06c5fe 100644 --- a/integration-test/java9/unnamedAutomaticModule/pom.xml +++ b/integration-test/java9/unnamedAutomaticModule/pom.xml @@ -39,7 +39,7 @@ - integration.test.java9.unnamedautomaticmodule + integration.test.javanine.unnamedautomaticmodule diff --git a/integration-test/java9/unnamedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/java9/unnamednonmodule/UnnamedAutomaticModuleTestClass.java b/integration-test/java9/unnamedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/unnamednonmodule/UnnamedAutomaticModuleTestClass.java similarity index 61% rename from integration-test/java9/unnamedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/java9/unnamednonmodule/UnnamedAutomaticModuleTestClass.java rename to integration-test/java9/unnamedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/unnamednonmodule/UnnamedAutomaticModuleTestClass.java index 3414d5b..b36b485 100644 --- a/integration-test/java9/unnamedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/java9/unnamednonmodule/UnnamedAutomaticModuleTestClass.java +++ b/integration-test/java9/unnamedAutomaticModule/src/main/java/io/toolisticon/cute/integrationtest/javanine/unnamednonmodule/UnnamedAutomaticModuleTestClass.java @@ -1,4 +1,4 @@ -package io.toolisticon.cute.integrationtest.java9.unnamednonmodule; +package io.toolisticon.cute.integrationtest.javanine.unnamednonmodule; public class UnnamedAutomaticModuleTestClass { diff --git a/integration-test/junit4/src/test/java/io/toolisticon/cute/integrationtest/junit4/Junit4Test.java b/integration-test/junit4/src/test/java/io/toolisticon/cute/integrationtest/junit4/Junit4Test.java index 63cc313..6f62925 100644 --- a/integration-test/junit4/src/test/java/io/toolisticon/cute/integrationtest/junit4/Junit4Test.java +++ b/integration-test/junit4/src/test/java/io/toolisticon/cute/integrationtest/junit4/Junit4Test.java @@ -1,18 +1,16 @@ package io.toolisticon.cute.integrationtest.junit4; -import io.toolisticon.cute.CompileTestBuilder; -import io.toolisticon.cute.UnitTest; +import io.toolisticon.cute.Cute; +import io.toolisticon.cute.UnitTestWithoutPassIn; import io.toolisticon.cute.extension.api.AssertionSpiServiceLocator; import io.toolisticon.cute.extension.junit4.JUnit4Assertion; -import io.toolisticon.cute.extension.plainjava.AssertionErrorAssertion; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Test; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; import javax.tools.Diagnostic; /** @@ -30,16 +28,17 @@ public void testServiceLocator() { @Test public void warningMessageTest() { - CompileTestBuilder + Cute .unitTest() - .defineTest(new UnitTest() { + .when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element typeElement) { + public void unitTest(ProcessingEnvironment processingEnvironment) { processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "WARNING!"); } }) - .expectWarningMessageThatContains("WARNING!") - .compilationShouldSucceed() + .thenExpectThat() + .compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().contains("WARNING!") .executeTest(); @@ -48,16 +47,17 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element typeEl @Test public void successfullFailingCompilationTest_ByErrorMessage() { - CompileTestBuilder + Cute .unitTest() - .defineTest(new UnitTest() { + .when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element element) { + public void unitTest(ProcessingEnvironment processingEnvironment) { processingEnvironment.getMessager().printMessage(Diagnostic.Kind.ERROR, "ERROR!"); } }) - .expectErrorMessageThatContains("ERROR!") - .compilationShouldFail() + .thenExpectThat() + .compilationFails() + .andThat().compilerMessage().ofKindError().contains("ERROR!") .executeTest(); @@ -67,15 +67,16 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element elemen public void failingCompilationTest_ByErrorMessage() { try { - CompileTestBuilder + Cute .unitTest() - .defineTest(new UnitTest() { + .when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element typeElement) { + public void unitTest(ProcessingEnvironment processingEnvironment) { processingEnvironment.getMessager().printMessage(Diagnostic.Kind.ERROR, "ERROR!"); } }) - .compilationShouldSucceed() + .thenExpectThat() + .compilationSucceeds() .executeTest(); Assert.fail("Should have failed"); diff --git a/integration-test/junit5/src/test/java/io/toolisticon/cute/integrationtest/junit5/Junit5Test.java b/integration-test/junit5/src/test/java/io/toolisticon/cute/integrationtest/junit5/Junit5Test.java index b1de845..40dc20b 100644 --- a/integration-test/junit5/src/test/java/io/toolisticon/cute/integrationtest/junit5/Junit5Test.java +++ b/integration-test/junit5/src/test/java/io/toolisticon/cute/integrationtest/junit5/Junit5Test.java @@ -1,8 +1,8 @@ package io.toolisticon.cute.integrationtest.junit5; -import io.toolisticon.cute.CompileTestBuilder; -import io.toolisticon.cute.UnitTest; +import io.toolisticon.cute.Cute; +import io.toolisticon.cute.UnitTestWithoutPassIn; import io.toolisticon.cute.extension.api.AssertionSpiServiceLocator; import io.toolisticon.cute.extension.junit5.JUnit5Assertion; import org.hamcrest.MatcherAssert; @@ -11,7 +11,6 @@ import org.junit.jupiter.api.Test; import javax.annotation.processing.ProcessingEnvironment; -import javax.lang.model.element.Element; import javax.tools.Diagnostic; /** @@ -29,34 +28,36 @@ public void testServiceLocator() { @Test public void warningMessageTest() { - CompileTestBuilder + Cute .unitTest() - .defineTest(new UnitTest() { + .when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element element) { + public void unitTest(ProcessingEnvironment processingEnvironment) { processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "WARNING!"); } }) - .expectWarningMessageThatContains("WARNING!") - .compilationShouldSucceed() + .thenExpectThat() + .compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().contains("WARNING!") .executeTest(); } @Test - public void successfullFailingCompilationTest_ByErrorMessage() { + public void successfulFailingCompilationTest_ByErrorMessage() { - CompileTestBuilder + Cute .unitTest() - .defineTest(new UnitTest() { + .when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element element) { + public void unitTest(ProcessingEnvironment processingEnvironment) { processingEnvironment.getMessager().printMessage(Diagnostic.Kind.ERROR, "ERROR!"); } }) - .expectErrorMessageThatContains("ERROR!") - .compilationShouldFail() + .thenExpectThat() + .compilationFails() + .andThat().compilerMessage().ofKindError().contains("ERROR!") .executeTest(); @@ -66,20 +67,20 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element elemen public void failingCompilationTest_ByErrorMessage() { try { - CompileTestBuilder + Cute .unitTest() - .defineTest(new UnitTest() { + .when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element element) { + public void unitTest(ProcessingEnvironment processingEnvironment) { processingEnvironment.getMessager().printMessage(Diagnostic.Kind.ERROR, "ERROR!"); } }) - .compilationShouldSucceed() + .thenExpectThat().compilationSucceeds() .executeTest(); Assertions.fail("Should have failed"); } catch (AssertionError error) { - Assertions.assertEquals(error.getMessage(), "Compilation should have succeeded but failed"); + Assertions.assertTrue(error.getMessage().startsWith("Compilation should have succeeded but failed")); } } diff --git a/integration-test/testng/src/test/java/io/toolisticon/cute/integrationtest/testng/TestNgTest.java b/integration-test/testng/src/test/java/io/toolisticon/cute/integrationtest/testng/TestNgTest.java index fdfc02e..fba96db 100644 --- a/integration-test/testng/src/test/java/io/toolisticon/cute/integrationtest/testng/TestNgTest.java +++ b/integration-test/testng/src/test/java/io/toolisticon/cute/integrationtest/testng/TestNgTest.java @@ -1,7 +1,8 @@ package io.toolisticon.cute.integrationtest.testng; -import io.toolisticon.cute.CompileTestBuilder; +import io.toolisticon.cute.Cute; import io.toolisticon.cute.UnitTest; +import io.toolisticon.cute.UnitTestWithoutPassIn; import io.toolisticon.cute.extension.api.AssertionSpiServiceLocator; import io.toolisticon.cute.extension.testng.TestNGAssertion; import org.hamcrest.MatcherAssert; @@ -28,17 +29,17 @@ public void testServiceLocator() { @Test public void warningMessageTest() { - CompileTestBuilder - + Cute .unitTest() - .defineTest(new UnitTest() { + .when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element typeElement) { + public void unitTest(ProcessingEnvironment processingEnvironment) { processingEnvironment.getMessager().printMessage(Diagnostic.Kind.WARNING, "WARNING!"); } }) - .expectWarningMessageThatContains("WARNING!") - .compilationShouldSucceed() + .thenExpectThat() + .compilationSucceeds() + .andThat().compilerMessage().ofKindWarning().contains("WARNING!") .executeTest(); @@ -47,16 +48,16 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element typeEl @Test public void successfullFailingCompilationTest_ByErrorMessage() { - CompileTestBuilder + Cute .unitTest() - .defineTest(new UnitTest() { + .when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element element) { + public void unitTest(ProcessingEnvironment processingEnvironment) { processingEnvironment.getMessager().printMessage(Diagnostic.Kind.ERROR, "ERROR!"); } }) - .expectErrorMessageThatContains("ERROR!") - .compilationShouldFail() + .thenExpectThat().compilationFails() + .andThat().compilerMessage().ofKindError().contains("ERROR!") .executeTest(); @@ -66,15 +67,15 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element elemen public void failingCompilationTest_ByErrorMessage() { try { - CompileTestBuilder + Cute .unitTest() - .defineTest(new UnitTest() { + .when(new UnitTestWithoutPassIn() { @Override - public void unitTest(ProcessingEnvironment processingEnvironment, Element element) { + public void unitTest(ProcessingEnvironment processingEnvironment) { processingEnvironment.getMessager().printMessage(Diagnostic.Kind.ERROR, "ERROR!"); } }) - .compilationShouldSucceed() + .thenExpectThat().compilationSucceeds() .executeTest(); Assert.fail("Should have failed"); diff --git a/legacy/pom.xml b/legacy/pom.xml new file mode 100644 index 0000000..5d3647d --- /dev/null +++ b/legacy/pom.xml @@ -0,0 +1,115 @@ + + 4.0.0 + + cute-legacy + jar + + + io.toolisticon.cute + cute-parent + 0.12.2-SNAPSHOT + + + cute-legacy + + + + + + io.toolisticon.cute + cute + + + + io.toolisticon.fluapigen + fluapigen-api + + + + + junit + junit + + + + + + + + + + + maven-compiler-plugin + + true + + + io.toolisticon.fluapigen + fluapigen-processor + ${fluapigen.version} + + + + + + + + maven-enforcer-plugin + + + enforce + + enforce + + + + + [3.0.4,) + + + 1.6 + + + false + + * + + + io.toolisticon.cute:* + io.toolisticon.fluapigen:* + *:*:*:*:test:* + *:*:*:*:provided:* + + + + + + + + + + + + + + + + + + java-9 + + [9,) + + + + + io.toolisticon.cute + extension-modulesupport + + + + + + + diff --git a/legacy/src/main/java/io/toolisticon/cute/CompileTestBuilderApi.java b/legacy/src/main/java/io/toolisticon/cute/CompileTestBuilderApi.java new file mode 100644 index 0000000..5b7dac8 --- /dev/null +++ b/legacy/src/main/java/io/toolisticon/cute/CompileTestBuilderApi.java @@ -0,0 +1,907 @@ +package io.toolisticon.cute; + +import io.toolisticon.cute.matchers.CoreGeneratedFileObjectMatchers; +import io.toolisticon.fluapigen.api.FluentApi; +import io.toolisticon.fluapigen.api.FluentApiBackingBean; +import io.toolisticon.fluapigen.api.FluentApiBackingBeanMapping; +import io.toolisticon.fluapigen.api.FluentApiCommand; +import io.toolisticon.fluapigen.api.FluentApiConverter; +import io.toolisticon.fluapigen.api.FluentApiImplicitValue; +import io.toolisticon.fluapigen.api.FluentApiInlineBackingBeanMapping; +import io.toolisticon.fluapigen.api.FluentApiInterface; +import io.toolisticon.fluapigen.api.FluentApiParentBackingBeanMapping; +import io.toolisticon.fluapigen.api.FluentApiRoot; +import io.toolisticon.fluapigen.api.MappingAction; +import io.toolisticon.fluapigen.api.TargetBackingBean; +import io.toolisticon.fluapigen.validation.api.HasNoArgConstructor; +import io.toolisticon.fluapigen.validation.api.NotNull; + +import javax.annotation.processing.Processor; +import javax.lang.model.element.Element; +import javax.tools.FileObject; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.StandardLocation; +import java.lang.annotation.Annotation; +import java.util.Arrays; +import java.util.Locale; + +@FluentApi("CompileTestBuilder") +public class CompileTestBuilderApi { + + /** + * ------------------------------------------------------------------------ + * BackingBeans + * ------------------------------------------------------------------------ + */ + + @FluentApiBackingBean + public interface CompilerTestBB extends CuteApi.CompilerTestBB { + + + } + + + @FluentApiBackingBean + public interface PassInConfigurationBB extends CuteApi.PassInConfigurationBB { + + } + + @FluentApiBackingBean + public interface CompilerMessageCheckBB extends CuteApi.CompilerMessageCheckBB { + + } + + + @FluentApiBackingBean + public interface GeneratedJavaFileObjectCheckBB extends CuteApi.GeneratedJavaFileObjectCheckBB { + + } + + @FluentApiBackingBean + public interface GeneratedFileObjectCheckBB extends CuteApi.GeneratedFileObjectCheckBB { + + } + + /** + * ------------------------------------------------------------------------ + * Fluent Interfaces + * ------------------------------------------------------------------------ + */ + + + /** + * Configures how FileObjects should be compared. + */ + public enum ExpectedFileObjectMatcherKind { + /** + * Does binary comparison. + * Be careful: tests using binary comparison may fail because of line-endings depending on OS. + */ + BINARY { + @Override + public GeneratedFileObjectMatcher createMatcher(T expectedFileObject) { + return CoreGeneratedFileObjectMatchers.createBinaryMatcher(expectedFileObject); + } + }, + /** + * Textual comparison line by line by ignoring the OS depending line-endings. + */ + TEXT_IGNORE_LINE_ENDINGS { + @Override + public GeneratedFileObjectMatcher createMatcher(T expectedFileObject) { + return CoreGeneratedFileObjectMatchers.createIgnoreLineEndingsMatcher(expectedFileObject); + } + }; + + /** + * Creates a matcher for FileObjects for enum value. + * + * @param expectedFileObject the expected FileObject + * @param The type of FileObject + * @return a GeneratedFileObjectMatcher instance that can be used to compare FileObjects + */ + protected abstract GeneratedFileObjectMatcher createMatcher(T expectedFileObject); + } + + + /** + * Abstract base builder class. + * Contains common configurations. + * + * @param The test-builder interface + * @param The compiler message check type + * The implementing type passed to base class + */ + public interface BasicBuilder, COMPILERMESSAGECHECK extends CompileMessageCheckBuilder> { + + /** + * Compilation is expected to be successful. + * + * @return the next builder instance + */ + @FluentApiImplicitValue(id = "compilationSucceeded", value = "true") + TEST_BUILDER compilationShouldSucceed(); + + /** + * Compilation is expected to be failing. + * + * @return the next builder instance + */ + @FluentApiImplicitValue(id = "compilationSucceeded", value = "false") + TEST_BUILDER compilationShouldFail(); + + /** + * Use compiler options. + * Options with parameters can, but must not be split over two consecutive Strings. + * Those options can be put in one single String (e.g. "-source 1.7" or "-target 1.7"). + * + * @param compilerOptions the options to use + * @return the next builder instance + */ + TEST_BUILDER useCompilerOptions(@FluentApiBackingBeanMapping("compilerOptions") String... compilerOptions); + + + /** + * Defines modules used during compilation. + * This configuration will be ignored for Java versions < 9. + * + * @param modules The modules to use during compilation + * @return the next builder instance + */ + TEST_BUILDER useModules(@FluentApiBackingBeanMapping("modules") String... modules); + + /** + * Starts a sub builder for adding a check for an error compiler message. + * + * @return an immutable builder instance for creating a complex compiler message check + */ + @FluentApiImplicitValue(id = "compilerMessageScope", value = "ERROR", target = TargetBackingBean.NEXT) + COMPILERMESSAGECHECK expectErrorMessage(); + + /** + * Starts a sub builder for adding a check for a mandatory warning compiler message. + * + * @return an immutable builder instance for creating a complex compiler message check + */ + @FluentApiImplicitValue(id = "compilerMessageScope", value = "MANDATORY_WARNING", target = TargetBackingBean.NEXT) + COMPILERMESSAGECHECK expectMandatoryWarningMessage(); + + /** + * Starts a sub builder for adding a check for a warning compiler message. + * + * @return an immutable builder instance for creating a complex compiler message check + */ + @FluentApiImplicitValue(id = "compilerMessageScope", value = "WARNING", target = TargetBackingBean.NEXT) + COMPILERMESSAGECHECK expectWarningMessage(); + + /** + * Starts a sub builder for adding a check for a note compiler message. + * + * @return an immutable builder instance for creating a complex compiler message check + */ + @FluentApiImplicitValue(id = "compilerMessageScope", value = "NOTE", target = TargetBackingBean.NEXT) + COMPILERMESSAGECHECK expectNoteMessage(); + + /** + * Adds some warning checks. + * + * @param warningChecks the warning checks to set, null values will be ignored. + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("compileMessageChecks") + @FluentApiImplicitValue(id = "compilerMessageScope", value = "WARNING", target = TargetBackingBean.INLINE) + @FluentApiImplicitValue(id = "compilerMessageComparisonType", value = "CONTAINS", target = TargetBackingBean.INLINE) + TEST_BUILDER expectWarningMessageThatContains(@FluentApiBackingBeanMapping(value = "searchString", target = TargetBackingBean.INLINE) @NotNull String... warningChecks); + + /** + * Adds some mandatory warning checks. + * + * @param mandatoryWarningChecks the mandatory warning checks to set, null values will be ignored. + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("compileMessageChecks") + @FluentApiImplicitValue(id = "compilerMessageScope", value = "MANDATORY_WARNING", target = TargetBackingBean.INLINE) + @FluentApiImplicitValue(id = "compilerMessageComparisonType", value = "CONTAINS", target = TargetBackingBean.INLINE) + TEST_BUILDER expectMandatoryWarningMessageThatContains(@FluentApiBackingBeanMapping(value = "searchString", target = TargetBackingBean.INLINE) @NotNull String... mandatoryWarningChecks); + + /** + * Adds some error checks. + * + * @param errorChecksToSet the error checks to set, null values will be ignored. + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("compileMessageChecks") + @FluentApiImplicitValue(id = "compilerMessageScope", value = "ERROR", target = TargetBackingBean.INLINE) + @FluentApiImplicitValue(id = "compilerMessageComparisonType", value = "CONTAINS", target = TargetBackingBean.INLINE) + TEST_BUILDER expectErrorMessageThatContains(@FluentApiBackingBeanMapping(value = "searchString", target = TargetBackingBean.INLINE) @NotNull String... errorChecksToSet); + + /** + * Adds some notes checks. + * + * @param noteChecksToSet the notes checks to set, null values will be ignored. + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("compileMessageChecks") + @FluentApiImplicitValue(id = "compilerMessageScope", value = "NOTE", target = TargetBackingBean.INLINE) + @FluentApiImplicitValue(id = "compilerMessageComparisonType", value = "CONTAINS", target = TargetBackingBean.INLINE) + TEST_BUILDER expectNoteMessageThatContains(@FluentApiBackingBeanMapping(value = "searchString", target = TargetBackingBean.INLINE) @NotNull String... noteChecksToSet); + + + /** + * Adds a check if a specific generated FileObject exists. + * + * @param location the location (usually a {@link StandardLocation}) + * @param packageName the package name + * @param relativeName the relative name to the passed package + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("fileObjectChecks") + @FluentApiImplicitValue(id = "checkType", value = "EXISTS", target = TargetBackingBean.INLINE) + TEST_BUILDER expectThatFileObjectExists(@FluentApiBackingBeanMapping(value = "location", target = TargetBackingBean.INLINE) JavaFileManager.Location location, @FluentApiBackingBeanMapping(value = "packageName", target = TargetBackingBean.INLINE) String packageName, @FluentApiBackingBeanMapping(value = "relativeName", target = TargetBackingBean.INLINE) String relativeName); + + /** + * Adds a check if a specific generated FileObject exists (uses binary comparision). + * Additionally, checks if files are equal if passed expectedFileObject is not null. + * + * @param location the location (usually from javax.tools.StandardLocation) + * @param packageName the package name + * @param relativeName the package relative name + * @param expectedFileObject the file used for comparison of content + * @return the next builder instance + */ + + default TEST_BUILDER expectThatFileObjectExists(JavaFileManager.Location location, String packageName, String relativeName, FileObject expectedFileObject) { + return expectThatFileObjectExists(location, packageName, relativeName, CoreGeneratedFileObjectMatchers.createBinaryMatcher(expectedFileObject)); + } + + /** + * Adds a check if a specific generated FileObject exists. + * Additionally, checks if files are equal if passed expectedFileObject is not null. + * Comparison algorithm can be selected by matcherKind parameter + * + * @param location the location (usually from javax.tools.StandardLocation) + * @param packageName the package name + * @param relativeName the package relative name + * @param matcherKind the matcher kind + * @param expectedFileObject the file used for comparison of content + * @return the next builder instance + */ + + default TEST_BUILDER expectThatFileObjectExists(JavaFileManager.Location location, String packageName, String relativeName, ExpectedFileObjectMatcherKind matcherKind, FileObject expectedFileObject) { + if (matcherKind == null || expectedFileObject == null) { + throw new IllegalArgumentException("Passed matcherKind and expectedFileObject must not be null!"); + } + return expectThatFileObjectExists(location, packageName, relativeName, matcherKind.createMatcher(expectedFileObject)); + } + + /** + * Adds a check if a specific generated FileObject exists. + * Additionally, checks if file object matches with passed matcher. + * + * @param location the location (usually from javax.tools.StandardLocation) + * @param packageName the package name + * @param relativeName the package relative name + * @param generatedFileObjectMatcher the matcher to use + * @return the next builder instance + */ + + @FluentApiInlineBackingBeanMapping("fileObjectChecks") + @FluentApiImplicitValue(id = "checkType", value = "EXISTS", target = TargetBackingBean.INLINE) + TEST_BUILDER expectThatFileObjectExists(@FluentApiBackingBeanMapping(value = "location", target = TargetBackingBean.INLINE) JavaFileManager.Location location, @FluentApiBackingBeanMapping(value = "packageName", target = TargetBackingBean.INLINE) String packageName, @FluentApiBackingBeanMapping(value = "relativeName", target = TargetBackingBean.INLINE) String relativeName, @FluentApiBackingBeanMapping(value = "generatedFileObjectMatcher", target = TargetBackingBean.INLINE) GeneratedFileObjectMatcher... generatedFileObjectMatcher); + + + /** + * Adds a check if a specific generated FileObject doesn't exist. + * + * @param location the location (usually from javax.tools.StandardLocation) + * @param packageName the package name + * @param relativeName the package relative name + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("fileObjectChecks") + @FluentApiImplicitValue(id = "checkType", value = "DOESNT_EXIST", target = TargetBackingBean.INLINE) + TEST_BUILDER expectThatFileObjectDoesntExist(@FluentApiBackingBeanMapping(value = "location", target = TargetBackingBean.INLINE) JavaFileManager.Location location, @FluentApiBackingBeanMapping(value = "packageName", target = TargetBackingBean.INLINE) String packageName, @FluentApiBackingBeanMapping(value = "relativeName", target = TargetBackingBean.INLINE) String relativeName); + + /** + * Checks if a generated source file exists. + * + * @param className the full qualified name of the class + * @return the next builder instance + */ + default TEST_BUILDER expectThatGeneratedSourceFileExists(String className) { + return expectThatJavaFileObjectExists(StandardLocation.SOURCE_OUTPUT, className, JavaFileObject.Kind.SOURCE); + } + + /** + * Checks if a generated source file exists and if it matches passed JavaFileObject by using binary comparision. + * Additionally, checks if files are equal if passed expectedJavaFileObject is not null.‚ + * + * @param className the full qualified name of the class + * @param expectedJavaFileObject the file used for comparision of content + * @return the next builder instance + */ + default TEST_BUILDER expectThatGeneratedSourceFileExists(String className, JavaFileObject expectedJavaFileObject) { + return expectThatGeneratedSourceFileExists(className, CoreGeneratedFileObjectMatchers.createBinaryMatcher(expectedJavaFileObject)); + } + + /** + * Adds a check if a specific class file exists. + * + * @param className the class name + * @return the next builder instance + */ + default TEST_BUILDER expectThatGeneratedClassExists(String className) { + return expectThatJavaFileObjectExists(StandardLocation.CLASS_OUTPUT, className, JavaFileObject.Kind.CLASS); + } + + /** + * Adds a check if a specific generated source file exists. + * Additionally, checks if java file object matches with passed matcher. + * + * @param className the class name + * @param generatedJavaFileObjectCheck the matcher to use + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("javaFileObjectChecks") + @FluentApiImplicitValue(id = "checkType", value = "EXISTS", target = TargetBackingBean.INLINE) + @FluentApiImplicitValue(id = "location", value = "SOURCE_OUTPUT", converter = StandardLocationStringToLocationConverter.class, target = TargetBackingBean.INLINE) + @FluentApiImplicitValue(id = "kind", value = "SOURCE", target = TargetBackingBean.INLINE) + TEST_BUILDER expectThatGeneratedSourceFileExists(@FluentApiBackingBeanMapping(value = "className", target = TargetBackingBean.INLINE) String className, @FluentApiBackingBeanMapping(value = "generatedFileObjectMatcher", target = TargetBackingBean.INLINE) GeneratedFileObjectMatcher generatedJavaFileObjectCheck); + + /** + * Adds a check if a specific JavaFileObject doesn't exist. + * + * @param className the class name + * @return the next builder instance + */ + + default TEST_BUILDER expectThatGeneratedSourceFileDoesntExist(String className) { + return expectThatJavaFileObjectDoesntExist(StandardLocation.SOURCE_OUTPUT, className, JavaFileObject.Kind.SOURCE); + } + + /** + * Adds a check if a specific JavaFileObject exists. + * + * @param location the location (usually from javax.tools.StandardLocation) + * @param className the class name + * @param kind the kind of the JavaFileObject + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("javaFileObjectChecks") + @FluentApiImplicitValue(id = "checkType", value = "EXISTS", target = TargetBackingBean.INLINE) + TEST_BUILDER expectThatJavaFileObjectExists(@FluentApiBackingBeanMapping(value = "location", target = TargetBackingBean.INLINE) JavaFileManager.Location location, @FluentApiBackingBeanMapping(value = "className", target = TargetBackingBean.INLINE) String className, @FluentApiBackingBeanMapping(value = "kind", target = TargetBackingBean.INLINE) JavaFileObject.Kind kind); + + + /** + * Adds a check if a specific generated JavaFileObject exists (uses binary comparision). + * Additionally, checks if files are equal if passed expectedJavaFileObject is not null. + * + * @param location the location (usually from javax.tools.StandardLocation) + * @param className the class name + * @param kind the kind of the JavaFileObject + * @param expectedJavaFileObject the file used for comparision of content + * @return the next builder instance + */ + + default TEST_BUILDER expectThatJavaFileObjectExists(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, JavaFileObject expectedJavaFileObject) { + return expectThatJavaFileObjectExists(location, className, kind, ExpectedFileObjectMatcherKind.BINARY.createMatcher(expectedJavaFileObject)); + } + + /** + * Adds a check if a specific generated JavaFileObject exists. + * Additionally, checks if files are equal if passed expectedJavaFileObject is not null. + * + * @param location the location (usually from javax.tools.StandardLocation) + * @param className the class name + * @param kind the kind of the JavaFileObject + * @param expectedJavaFileObject the file used for comparision of content + * @return the next builder instance + */ + default TEST_BUILDER expectThatJavaFileObjectExists(JavaFileManager.Location location, String className, JavaFileObject.Kind kind, ExpectedFileObjectMatcherKind expectedFileObjectMatcherKind, JavaFileObject expectedJavaFileObject) { + return expectThatJavaFileObject(CuteApi.FileObjectCheckType.EXISTS, location, className, kind, CoreGeneratedFileObjectMatchers.createBinaryMatcher(expectedJavaFileObject)); + } + + /** + * Adds a check if a specific generated JavaFileObject exists. + * Additionally, checks if java file object matches with passed matcher. + * + * @param location the location (usually a {@link StandardLocation}) + * @param className the class name + * @param kind the kind of the JavaFileObject + * @param generatedJavaFileObjectCheck the matcher to use + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("javaFileObjectChecks") + @FluentApiImplicitValue(id = "checkType", value = "EXISTS", target = TargetBackingBean.INLINE) + default TEST_BUILDER expectThatJavaFileObjectExists(@FluentApiBackingBeanMapping(value = "location", target = TargetBackingBean.INLINE) JavaFileManager.Location location, @FluentApiBackingBeanMapping(value = "className", target = TargetBackingBean.INLINE) String className, @FluentApiBackingBeanMapping(value = "kind", target = TargetBackingBean.INLINE) JavaFileObject.Kind kind, @FluentApiBackingBeanMapping(value = "generatedFileObjectMatcher", target = TargetBackingBean.INLINE) GeneratedFileObjectMatcher generatedJavaFileObjectCheck) { + return expectThatJavaFileObject(CuteApi.FileObjectCheckType.EXISTS, location, className, kind, generatedJavaFileObjectCheck); + } + + + /** + * Adds a check if a specific generated JavaFileObject exists or doesn't exist. + * Additionally, checks if java file object matches with passed matcher. + * + * @param checkType the kind of check + * @param location the location (usually a {@link StandardLocation}) + * @param className the class name + * @param kind the kind of the JavaFileObject + * @param generatedJavaFileObjectCheck the matcher to use + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("javaFileObjectChecks") + TEST_BUILDER expectThatJavaFileObject(@FluentApiBackingBeanMapping(value = "checkType", target = TargetBackingBean.INLINE) CuteApi.FileObjectCheckType checkType, @FluentApiBackingBeanMapping(value = "location", target = TargetBackingBean.INLINE) JavaFileManager.Location location, @FluentApiBackingBeanMapping(value = "className", target = TargetBackingBean.INLINE) String className, @FluentApiBackingBeanMapping(value = "kind", target = TargetBackingBean.INLINE) JavaFileObject.Kind kind, @FluentApiBackingBeanMapping(value = "generatedFileObjectMatcher", target = TargetBackingBean.INLINE) GeneratedFileObjectMatcher generatedJavaFileObjectCheck); + + /** + * Adds a check if a specific JavaFileObject doesn't exist. + * + * @param location the location (usually from javax.tools.StandardLocation) + * @param className the class name + * @param kind the kind of the JavaFileObject + * @return the next builder instance + */ + @FluentApiInlineBackingBeanMapping("javaFileObjectChecks") + @FluentApiImplicitValue(id = "checkType", value = "DOESNT_EXIST", target = TargetBackingBean.INLINE) + TEST_BUILDER expectThatJavaFileObjectDoesntExist(@FluentApiBackingBeanMapping(value = "location", target = TargetBackingBean.INLINE) JavaFileManager.Location location, @FluentApiBackingBeanMapping(value = "className", target = TargetBackingBean.INLINE) String className, @FluentApiBackingBeanMapping(value = "kind", target = TargetBackingBean.INLINE) JavaFileObject.Kind kind); + + /** + * Created the compile-test configuration instance. + * + * @return the configuration instance + */ + + @FluentApiCommand(ClosingCommand.class) + CompilerTestBB createCompileTestConfiguration(); + + /** + * Executes the compilation tests. + * + * @throws IllegalStateException if there's some invalid configuration + */ + @FluentApiCommand(ExecuteTestCommand.class) + void executeTest(); + + + } + + /** + * Builder class used to create compile tests (== Integration tests). + * Class is designed to produce immutable builder instances in its fluent api. + */ + @FluentApiInterface(CompilerTestBB.class) + public interface CompilationTestBuilder extends BasicBuilder { + + + /** + * Adds processors. + * + * @param processorTypes the processor types to use, processors must have a noarg constructor + * @return the CompilationTestBuilder instance + */ + CompilationTestBuilder addProcessors(@FluentApiBackingBeanMapping(value = "processors", converter = ProcessorConverter.class, action = MappingAction.ADD) @HasNoArgConstructor() Class... processorTypes); + + + /** + * Adds source files to compile to compilation test. + * + * @param sources the sources to use + * @return the CompilationTestBuilder instance + */ + CompilationTestBuilder addSources(@FluentApiBackingBeanMapping(value = "sourceFiles", action = MappingAction.ADD) JavaFileObject... sources); + + /** + * Adds source files to compile to compilation test. + * Sources will be read from resources. + * Source file names must either end with ".java" or ".java.ct". + * + * @param sources the sources to use + * @return the CompilationTestBuilder instance + */ + default CompilationTestBuilder addSources(String... sources) { + return addSources(Arrays.stream(sources).map(e -> JavaFileObjectUtils.readFromResource(e)).toArray(JavaFileObject[]::new)); + } + + /** + * Add a source file for String. + * + * @param clazzName The package name + * @param content The content to check for + * @return the CompilationTestBuilder instance + */ + default CompilationTestBuilder addSource(String clazzName, String content) { + return addSources(JavaFileObjectUtils.readFromString(clazzName, content)); + } + } + + @FluentApiInterface(CompilerTestBB.class) + public interface UnitTestBuilder extends BasicBuilder { + + /** + * Sets the processor to use. + * The processor should support {@link TestAnnotation} annotation processing if no custom source file is defined. + * If custom source is used you need to define a processor that is going to process the source file. + * + * @param processor the processor to use + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed processor is null. + */ + UnitTestBuilder useProcessor(@FluentApiBackingBeanMapping(value = "processors", action = MappingAction.SET) @NotNull Class processor); + + /** + * Allows writing of unit tests. + * You can pass in a {@link UnitTest} instance that contains your test code in it's unitTest method. + *

+ * The {@link javax.annotation.processing.ProcessingEnvironment} and an Element of type ELEMENT_TYPE will passed to the UnitTestProcessor.unitTest method. + *

+ * The {@link TestAnnotation} will be used to look up this Element during compilation. + *

+ * So please make sure that the {@link TestAnnotation} is used exactly once, when you are using a custom source files + * + * @param unitTest the processor to use + * @param The expected element type (Must be TypeElement, if no custom source files are used) + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed processor is null. + * @throws IllegalStateException if more than one Element is found or if ELEMENT_TYPE doesn't match type of the found element + */ + UnitTestBuilder defineTest(@FluentApiBackingBeanMapping("unitTest") @NotNull UnitTest unitTest); + + /** + * Allows writing of unit tests. + * You can pass in a {@link UnitTest} instance that contains your test code in it's unitTest method. + *

+ * The {@link javax.annotation.processing.ProcessingEnvironment} and an Element of type ELEMENT_TYPE will passed to the UnitTestProcessor.unitTest method. + *

+ * The passed customAnnotationTyoe will be used to look up this Element. + *

+ * So please make sure that the customAnnotationType annotation is used exactly once in your custom source file that. + * + * @param customAnnotationType the annotation type to search the element for + * @param unitTest the processor to use + * @param The expected element type (Must be TypeElement, if no custom source files are used) + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed processor is null. + * @throws IllegalStateException if more than one Element is found or if ELEMENT_TYPE doesn't match type of the found element + */ + @FluentApiInlineBackingBeanMapping("passInConfiguration") + @FluentApiImplicitValue(id = "passInElement", value = "true", target = TargetBackingBean.INLINE) + UnitTestBuilder defineTest( + @FluentApiBackingBeanMapping(value = "annotationToScanFor", target = TargetBackingBean.INLINE) @NotNull Class customAnnotationType, + @FluentApiBackingBeanMapping("unitTest") @NotNull UnitTest unitTest); + + /** + * Allows writing of unit tests. + * You can pass in a {@link UnitTest} instance that contains your test code in it's unitTest method. + *

+ * The {@link javax.annotation.processing.ProcessingEnvironment} and an Element of type ELEMENT_TYPE will passed to the UnitTestProcessor.unitTest method. + *

+ * The {@link PassIn} will be used to look up this Element. + *

+ * + * @param classToScan the class to search element annotated with {@link PassIn} + * @param unitTest the processor to use + * @param The expected element type (Must be TypeElement, if no custom source files are used) + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed processor is null. + * @throws IllegalStateException if more than one Element is found or if ELEMENT_TYPE doesn't match type of the found element + */ + default UnitTestBuilder defineTestWithPassedInElement(Class classToScan, UnitTest unitTest) { + return defineTestWithPassedInElement(classToScan, PassIn.class, unitTest); + } + + /** + * Allows writing of unit tests. + * You can pass in a {@link UnitTest} instance that contains your test code in it's unitTest method. + *

+ * The {@link javax.annotation.processing.ProcessingEnvironment} and an Element of type ELEMENT_TYPE will be passed to the UnitTestProcessor.unitTest method. + *

+ * The {@link PassIn} will be used to look up this Element. + *

+ * + * @param classToScan the class to search element annotated with annotationToSearch + * @param annotationToSearch the annotation type to search for + * @param unitTest the processor to use + * @param The expected element type (Must be TypeElement, if no custom source files are used) + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed processor is null. + * @throws IllegalStateException if more than one Element is found or if ELEMENT_TYPE doesn't match type of the found element + */ + @FluentApiInlineBackingBeanMapping("passInConfiguration") + @FluentApiImplicitValue(id = "passInElement", value = "true", target = TargetBackingBean.INLINE) + UnitTestBuilder defineTestWithPassedInElement( + @FluentApiBackingBeanMapping(value = "passedInClass", target = TargetBackingBean.INLINE) @NotNull Class classToScan, + @FluentApiBackingBeanMapping(value = "annotationToScanFor", target = TargetBackingBean.INLINE) @NotNull Class annotationToSearch, + @FluentApiBackingBeanMapping("unitTest") @NotNull UnitTest unitTest); + + /** + * Allows unit + * Provides a specific processor instance that can be used for unit testing. + * Additionally, it provides an element + * The passed processor won't be used as an annotation processor during compilation. + *

+ * It will internally use a generic processor that + * The processor should support {@link TestAnnotation} annotation processing if no custom source file is defined. + * If custom source is used make sure {@link TestAnnotation} is used somewhere in the custom source file to make sure if annotation processor is used. + * + * @param processorUnderTestClass the Processor which should be provided as a + * @param unitTestForTestingAnnotationProcessors the processor to use + * @param The processor type under test + * @param The expected element type to be processed + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed processor is null. + * @throws IllegalStateException if more than one Element is found or if ELEMENT_TYPE doesn't match type of the found element + */ + @FluentApiInlineBackingBeanMapping("passInConfiguration") + UnitTestBuilder defineTest( + @FluentApiBackingBeanMapping(value = "passedInProcessor", target = TargetBackingBean.INLINE) @NotNull @HasNoArgConstructor Class processorUnderTestClass, + @FluentApiBackingBeanMapping("unitTest") @NotNull UnitTestForTestingAnnotationProcessors unitTestForTestingAnnotationProcessors); + + /** + * Sets the processor to use. + * The processor should support annotation processing of passed annotation type if no custom source file is defined. + * Please make sure to add a custom source files in which the customAnnotationType annotation is used exactly once. + * + * @param processorUnderTestClass the Processor type + * @param customAnnotationType the custom annotation used to search the element to pass be passed in + * @param unitTestForTestingAnnotationProcessors the processor to use + * @param The processor type under test + * @param The expected element type to be processed + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed processor or customAnnotationType is null. + * @throws IllegalStateException if more than one Element is found or if ELEMENT_TYPE doesn't match type of the found element + */ + default UnitTestBuilder defineTest(Class processorUnderTestClass, Class customAnnotationType, UnitTestForTestingAnnotationProcessors unitTestForTestingAnnotationProcessors) { + return defineTestWithPassedInElement(processorUnderTestClass, null, customAnnotationType, unitTestForTestingAnnotationProcessors); + } + + /** + * Sets the processor to use. + * The processor should support annotation processing of passed annotation type if no custom source file is defined. + * Please make sure to add a custom source file in which the customAnnotationType annotation is used exactly once. + * + * @param processorUnderTestClass the Processor type + * @param classToScan the type to search the PassIn element + * @param unitTestForTestingAnnotationProcessors the processor to use + * @param The processor type under test + * @param The expected element type to be processed + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed processor or customAnnotationType is null. + * @throws IllegalStateException if more than one Element is found or if ELEMENT_TYPE doesn't match type of the found element + */ + default UnitTestBuilder defineTestWithPassedInElement(Class processorUnderTestClass, Class classToScan, UnitTestForTestingAnnotationProcessors unitTestForTestingAnnotationProcessors) { + return defineTestWithPassedInElement(processorUnderTestClass, classToScan, PassIn.class, unitTestForTestingAnnotationProcessors); + } + + /** + * Sets the processor to use. + * The processor should support annotation processing of passed annotation type if no custom source file is defined. + * Please make sure to add a custom source file in which the customAnnotationType annotation is used exactly once. + * + * @param processorUnderTestClass the Processor type + * @param classToScan the type to search the PassIn element + * @param annotationToSearch annotation to search + * @param unitTestForTestingAnnotationProcessors the processor to use + * @param The processor type under test + * @param The expected element type to be processed + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed processor or customAnnotationType is null. + * @throws IllegalStateException if more than one Element is found or if ELEMENT_TYPE doesn't match type of the found element + */ + @FluentApiInlineBackingBeanMapping("passInConfiguration") + @FluentApiImplicitValue(id = "passInElement", value = "true", target = TargetBackingBean.INLINE) + UnitTestBuilder defineTestWithPassedInElement( + @FluentApiBackingBeanMapping(value = "passedInProcessor", target = TargetBackingBean.INLINE) Class processorUnderTestClass, + @FluentApiBackingBeanMapping(value = "passedInClass", target = TargetBackingBean.INLINE) Class classToScan, + @FluentApiBackingBeanMapping(value = "annotationToScanFor", target = TargetBackingBean.INLINE) Class annotationToSearch, + @FluentApiBackingBeanMapping("unitTest") UnitTestForTestingAnnotationProcessors unitTestForTestingAnnotationProcessors + ); + + /** + * Sets the source file used to apply processor on. + * The source file must contain an annotation that is processed by the processor. + * + * @param source The source file to use + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed source is null. + */ + UnitTestBuilder useSource(@FluentApiBackingBeanMapping(value = "sourceFiles", action = MappingAction.SET) @NotNull JavaFileObject source); + + /** + * Sets the source file used to apply processor on. + * The referenced resource file must contain an annotation that is processed by the processor. + * The source file name must either end with ".java" or ".java.ct". + * + * @param resource The resource file to use + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed source is null. + */ + default UnitTestBuilder useSource(String resource) { + return useSource(JavaFileObjectUtils.readFromResource(resource)); + } + + /** + * Sets the source file used to apply processor on. + * The source file will be added from String. + * + * @param className The name of the file passed in as a class name (fqn or simple class name) + * @return the UnitTestBuilder instance + * @throws IllegalArgumentException if passed source is null. + */ + default UnitTestBuilder useSource(String className, String content) { + return useSource(JavaFileObjectUtils.readFromString(className, content)); + } + + /** + * Sets an expected exception thrown in the unit test case. + * + * @param expectedException the exceptions expected to be thrown + * @return the UnitTestBuilder instance + */ + UnitTestBuilder expectedThrownException(@FluentApiBackingBeanMapping(value = "exceptionIsThrown") Class expectedException); + + + /** + * {@inheritDoc} + */ + + @FluentApiCommand(ExecuteTestCommand.class) + void executeTest(); + + + } + + /** + * Fluent immutable builder for creation of complex compiler message checks. + * + * @param The enclosing builder. + * @param > The compiler message interface + */ + + public interface CompileMessageCheckBuilder, COMPILERMESSAGEBUILDER extends CompileMessageCheckBuilder> { + + /** + * The line number to search the compiler message at. + * + * @param lineNumber the line number to check for.Line check will be skipped if passed lineNumber is null. + * @return the next immutable builder instance + */ + COMPILERMESSAGEBUILDER atLineNumber(@FluentApiBackingBeanMapping(value = "atLine", converter = FluentApiConverter.LongToIntegerConverter.class) Long lineNumber); + + /** + * The column number to search the compiler message at. + * + * @param columnNumber the column number to check for. Column check will be skipped if passed columnNumber is null. + * @return the next immutable builder instance + */ + + COMPILERMESSAGEBUILDER atColumnNumber(@FluentApiBackingBeanMapping(value = "atColumn", converter = FluentApiConverter.LongToIntegerConverter.class) Long columnNumber); + + /** + * Do check for localized compiler message. + * + * @param locale the locale to use, or null for default locale. + * @return the next immutable builder instance + */ + COMPILERMESSAGEBUILDER withLocale(@FluentApiBackingBeanMapping("withLocale") Locale locale); + + /** + * Do check if compiler message is linked for a specific source + * + * @param source the source + * @return the next immutable builder instance + */ + COMPILERMESSAGEBUILDER atSource(@FluentApiBackingBeanMapping("atSource") String source); + + /** + * Check if a compiler message exists that contains the passed message token. + * May be used for checking for message codes. + * + * @param expectedContainedMessageToken the message to search for + * @return the next immutable builder instance of enclosing builder + */ + @FluentApiParentBackingBeanMapping(value = "compileMessageChecks", action = MappingAction.ADD) + @FluentApiImplicitValue(id = "compilerMessageComparisonType", value = "CONTAINS") + COMPILETESTBUILDER thatContains(@FluentApiBackingBeanMapping(value = "searchString") String expectedContainedMessageToken); + + /** + * Check if a compiler message matches the passed message string. + * + * @param expectedMessage the message to search for + * @return the next immutable builder instance of enclosing builder + */ + @FluentApiParentBackingBeanMapping(value = "compileMessageChecks", action = MappingAction.ADD) + @FluentApiImplicitValue(id = "compilerMessageComparisonType", value = "EQUALS") + COMPILETESTBUILDER thatIsEqualTo(@FluentApiBackingBeanMapping(value = "searchString") String expectedMessage); + + + } + + @FluentApiInterface(CompilerMessageCheckBB.class) + public interface UnitTestCompileMessageCheckBuilder extends CompileMessageCheckBuilder { + + } + + @FluentApiInterface(CompilerMessageCheckBB.class) + public interface CompilationTestCompileMessageCheckBuilder extends CompileMessageCheckBuilder { + + } + + /** + * Internal builder class for unit and compilation tests. + */ + @FluentApiInterface(CompilerTestBB.class) + @FluentApiRoot + public interface TestTypeBuilder { + + /** + * Does a compilation test. + * You can freely choose sources to compile and processors to use. + * + * @return the builder + */ + @FluentApiImplicitValue(id = "testType", value = "BLACK_BOX") + CompilationTestBuilder compilationTest(); + + + /** + * Do a unit test. + * + * @return the UnitTestBuilder instance + */ + @FluentApiImplicitValue(id = "testType", value = "UNIT") + UnitTestBuilder unitTest(); + + } + + + /** + * ------------------------------------------------------------------------ + * Commands + * ------------------------------------------------------------------------ + */ + + @FluentApiCommand + public static class ClosingCommand { + public static CompilerTestBB getConfig(CompilerTestBB compilerTestBB) { + return compilerTestBB; + } + } + + @FluentApiCommand + public static class ExecuteTestCommand { + static void myCommand(CuteApi.CompilerTestBB backingBean) { + if (backingBean.testType() == CuteApi.TestType.UNIT && backingBean.sourceFiles().size() == 0) { + backingBean.sourceFiles().add(JavaFileObjectUtils.readFromResource("/AnnotationProcessorUnitTestClass.java")); + } + if (backingBean.testType() == CuteApi.TestType.BLACK_BOX && backingBean.sourceFiles().size() == 0) { + throw new IllegalStateException("There must be at least one source file present to execute a black box test!"); + } + new CompileTest(backingBean).executeTest(); + } + } + + /** + * ------------------------------------------------------------------------ + * Converters + * ------------------------------------------------------------------------ + */ + + public static class StandardLocationStringToLocationConverter implements FluentApiConverter { + + @Override + public StandardLocation convert(String s) { + return StandardLocation.valueOf(s); + } + + } + + public static class ProcessorConverter implements FluentApiConverter[], Class[]> { + + @Override + public Class[] convert(Class[] processor) { + return (Class[]) processor; + } + + } + +} diff --git a/cute/src/main/java/io/toolisticon/cute/CompileTestBuilder.java b/legacy/src/main/java/io/toolisticon/cute/CompileTestBuilderOld.javax similarity index 99% rename from cute/src/main/java/io/toolisticon/cute/CompileTestBuilder.java rename to legacy/src/main/java/io/toolisticon/cute/CompileTestBuilderOld.javax index 2909309..26aee76 100644 --- a/cute/src/main/java/io/toolisticon/cute/CompileTestBuilder.java +++ b/legacy/src/main/java/io/toolisticon/cute/CompileTestBuilderOld.javax @@ -18,7 +18,7 @@ * Compile test builder. * Implemented with immutable state / configuration, so it's safe to create a base configuration in test class and to further specify the tests in the unit test method. */ -public class CompileTestBuilder { +public class CompileTestBuilderOld { /** * Configures how FileObjects should be compared. @@ -250,7 +250,7 @@ T addCompilerMessageCheck(CompileTestConfiguration.CompilerMessageCheck compiler /** * Adds a check if a specific generated FileObject exists. * - * @param location the location (usually a {@link javax.tools.StandardLocation}) + * @param location the location (usually a {@link StandardLocation}) * @param packageName the package name * @param relativeName the relative name to the passed package * @return the next builder instance @@ -315,7 +315,7 @@ public T expectThatFileObjectExists( /** * Adds a check if a specific generated FileObject exists. - * Additionally checks if file object matches with passed matcher. + * Additionally, checks if file object matches with passed matcher. * * @param location the location (usually from javax.tools.StandardLocation) * @param packageName the package name @@ -470,7 +470,7 @@ public T expectThatJavaFileObjectExists( * Adds a check if a specific generated JavaFileObject exists. * Additionally checks if java file object matches with passed matcher. * - * @param location the location (usually a {@link javax.tools.StandardLocation}) + * @param location the location (usually a {@link StandardLocation}) * @param className the class name * @param kind the kind of the JavaFileObject * @param generatedJavaFileObjectCheck the matcher to use diff --git a/cute/src/test/java/io/toolisticon/cute/CompileTestBuilderTest.java b/legacy/src/test/java/io/toolisticon/cute/CompileTestBuilderTest.java similarity index 76% rename from cute/src/test/java/io/toolisticon/cute/CompileTestBuilderTest.java rename to legacy/src/test/java/io/toolisticon/cute/CompileTestBuilderTest.java index decd490..e2b69d3 100644 --- a/cute/src/test/java/io/toolisticon/cute/CompileTestBuilderTest.java +++ b/legacy/src/test/java/io/toolisticon/cute/CompileTestBuilderTest.java @@ -2,7 +2,7 @@ import io.toolisticon.cute.common.SimpleTestProcessor1; import io.toolisticon.cute.common.SimpleTestProcessor2; -import io.toolisticon.cute.impl.CompileTestConfiguration; +import io.toolisticon.fluapigen.validation.api.ValidatorException; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.Test; @@ -24,6 +24,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -170,18 +171,18 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element typeEl } - private void assertCompilerMessages(Set compilerMessageChecks, Diagnostic.Kind kind, CompileTestConfiguration.ComparisonKind comparisonKind, String... expectedMessages) { + private void assertCompilerMessages(List compilerMessageChecks, CuteApi.CompilerMessageKind kind, CuteApi.CompilerMessageComparisonType comparisonKind, String... expectedMessages) { List configuredExpectedMessages = new ArrayList<>(); - Iterator iterator = compilerMessageChecks.iterator(); + Iterator iterator = compilerMessageChecks.iterator(); while (iterator.hasNext()) { - CompileTestConfiguration.CompilerMessageCheck element = iterator.next(); + CuteApi.CompilerMessageCheckBB element = iterator.next(); - MatcherAssert.assertThat(element.getComparisonKind(), Matchers.is(comparisonKind)); + MatcherAssert.assertThat(element.getComparisonType(), Matchers.is(comparisonKind)); MatcherAssert.assertThat(element.getKind(), Matchers.is(kind)); - configuredExpectedMessages.add(element.getExpectedMessage()); + configuredExpectedMessages.addAll(element.getSearchString()); } @@ -192,102 +193,104 @@ private void assertCompilerMessages(SetdefineTest(PassIn.class, new UnitTest() { @Override public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement element) { - MatcherAssert.assertThat("io.toolisticon.annotationprocessortoolkit.testhelper.TestClass" , Matchers.is(element.getQualifiedName().toString())); + MatcherAssert.assertThat("io.toolisticon.annotationprocessortoolkit.testhelper.TestClass", Matchers.is(element.getQualifiedName().toString())); } }).compilationShouldSucceed() - .expectThatJavaFileObjectExists(StandardLocation.CLASS_OUTPUT,"io.toolisticon.annotationprocessortoolkit.testhelper.TestClass", JavaFileObject.Kind.CLASS) + .expectThatJavaFileObjectExists(StandardLocation.CLASS_OUTPUT, "io.toolisticon.annotationprocessortoolkit.testhelper.TestClass", JavaFileObject.Kind.CLASS) .executeTest(); } @@ -388,18 +390,19 @@ public void test_useProcessors() { Class testProcessor1 = SimpleTestProcessor1.class; Class testProcessor2 = SimpleTestProcessor2.class; - CompileTestBuilder.CompilationTestBuilder builder = CompileTestBuilder + CompileTestBuilderApi.CompilationTestBuilder builder = CompileTestBuilder .compilationTest() .addProcessors(testProcessor1) - .addProcessors(testProcessor2) - .addProcessors((Class) null); + .addProcessors(testProcessor2); - MatcherAssert.assertThat(builder.createCompileTestConfiguration().getProcessorTypes(), Matchers.containsInAnyOrder(testProcessor1, testProcessor2)); + MatcherAssert.assertThat(builder.createCompileTestConfiguration().processors(), Matchers.containsInAnyOrder(testProcessor1, testProcessor2)); } + // TODO: HOWTO HANDLE EXPECTED EXCEPTIONS OF PROCESSOR + /*- @Test public void test_useProcessorAndExpectException() { @@ -416,17 +419,17 @@ public void test_useProcessorAndExpectException() { } - + */ @Test public void test_useSource_addSingleSource() { JavaFileObject javaFileObject = Mockito.mock(JavaFileObject.class); - CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + CompileTestBuilderApi.UnitTestBuilder builder = CompileTestBuilder .unitTest() .useSource(javaFileObject); - MatcherAssert.assertThat(builder.createCompileTestConfiguration().getSourceFiles(), Matchers.contains(javaFileObject)); + MatcherAssert.assertThat(builder.createCompileTestConfiguration().sourceFiles(), Matchers.contains(javaFileObject)); } @@ -436,20 +439,20 @@ public void test_useSource_addSourceTwice_onlySecondSourceShouldBeUsed() { JavaFileObject javaFileObject1 = Mockito.mock(JavaFileObject.class); JavaFileObject javaFileObject2 = Mockito.mock(JavaFileObject.class); - CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + CompileTestBuilderApi.UnitTestBuilder builder = CompileTestBuilder .unitTest() .useSource(javaFileObject1) .useSource(javaFileObject2); - MatcherAssert.assertThat(builder.createCompileTestConfiguration().getSourceFiles(), Matchers.contains(javaFileObject2)); + MatcherAssert.assertThat(builder.createCompileTestConfiguration().sourceFiles(), Matchers.contains(javaFileObject2)); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = ValidatorException.class) public void test_useSource_addNullValuedSource_asJavaFileObject() { - CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + CompileTestBuilderApi.UnitTestBuilder builder = CompileTestBuilder .unitTest() .useSource((JavaFileObject) null); @@ -460,40 +463,39 @@ public void test_useSource_addNullValuedSource_asJavaFileObject() { public void test_useSource_addNullValuedSource_asString() { - CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + CompileTestBuilderApi.UnitTestBuilder builder = CompileTestBuilder .unitTest() .useSource((String) null); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = ValidatorException.class) public void test_useProcessor_addNullValuedProcessor() { - CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + CompileTestBuilderApi.UnitTestBuilder builder = CompileTestBuilder .unitTest() - .useProcessor((Processor) null); + .useProcessor((Class) null); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = ValidatorException.class) public void test_useProcessor_addNullValuedUnitTestProcessor() { - CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + CompileTestBuilderApi.UnitTestBuilder builder = CompileTestBuilder .unitTest() .defineTest((UnitTest) null); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = ValidatorException.class) public void test_useProcessor_nonInstantiableConstructorForProcessorUnderTest() { - - CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + CompileTestBuilderApi.UnitTestBuilder builder = CompileTestBuilder .unitTest() .defineTest(AbstractProcessor.class, new UnitTestForTestingAnnotationProcessors() { @Override @@ -502,14 +504,13 @@ public void unitTest(AbstractProcessor unit, ProcessingEnvironment processingEnv } }); - } - @Test(expected = IllegalArgumentException.class) + @Test(expected = ValidatorException.class) public void test_useProcessor_nullProcessorUnderTestClass() { - CompileTestBuilder.UnitTestBuilder builder = CompileTestBuilder + CompileTestBuilderApi.UnitTestBuilder builder = CompileTestBuilder .unitTest() .defineTest(null, new UnitTestForTestingAnnotationProcessors() { @Override @@ -626,22 +627,24 @@ public void unitTest(ProcessingEnvironment processingEnvironment, Element elemen } - @Test(expected = IllegalArgumentException.class) + @Test(expected = ValidatorException.class) public void test_useProcessor_nullValued_Processor() { - CompileTestBuilder.unitTest().useProcessor((Processor) null); + CompileTestBuilder.unitTest().useProcessor(null); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = ValidatorException.class) public void test_useProcessor_nullValued_UnitTestProcessor() { CompileTestBuilder.unitTest().defineTest((UnitTest) null); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = ValidatorException.class) public void test_useProcessor_nullValued_UnitTestProcessor2() { CompileTestBuilder.unitTest().defineTest(AbstractProcessor.class, null); } + //TODO: MUST DECIDE HOW TO HANDLE EXPECTED EXCEPTIONS OF PROCESSORS + /*- @Test(expected = IllegalArgumentException.class) public void test_CompileTimeTestBuilder_useProcessorAndExpectException_addNullValuedProcessor() { @@ -651,6 +654,7 @@ public void test_CompileTimeTestBuilder_useProcessorAndExpectException_addNullVa } + */ private static class SimpleTestProcessor extends AbstractProcessor { @Override @@ -659,6 +663,8 @@ public boolean process(Set annotations, RoundEnvironment } } + //TODO: MUST DECIDE HOW TO HANDLE EXPECTED EXCEPTIONS OF PROCESSORS +/*- @Test(expected = IllegalArgumentException.class) public void test_CompileTimeTestBuilder_useProcessorAndExpectException_addNullValuedException() { @@ -668,6 +674,7 @@ public void test_CompileTimeTestBuilder_useProcessorAndExpectException_addNullVa } +*/ @Test(expected = IllegalStateException.class) public void test_CompileTimeTestBuilder_testCompilation_noSourceFiles() { @@ -682,22 +689,22 @@ public void test_CompileTimeTestBuilder_testCompilation_noSourceFiles() { @Test public void test_useModules() { - MatcherAssert.assertThat(CompileTestBuilder.compilationTest().useModules("ABC", "DEF").compileTestConfiguration.getModules(), Matchers.contains("ABC", "DEF")); + MatcherAssert.assertThat(CompileTestBuilder.compilationTest().useModules("ABC", "DEF").createCompileTestConfiguration().modules(), Matchers.contains("ABC", "DEF")); } @Test public void test_addCompilerMessageCheck() { - CompileTestConfiguration configuration = CompileTestBuilder.compilationTest().expectErrorMessage().atSource("XYZ").atLineNumber(5L).atColumnNumber(6L).withLocale(Locale.ENGLISH).thatContains("ABC").compileTestConfiguration; - CompileTestConfiguration.CompilerMessageCheck compilerMessageCheck = configuration.getCompilerMessageChecks().iterator().next(); - MatcherAssert.assertThat(compilerMessageCheck.getSource(), Matchers.is("XYZ")); - MatcherAssert.assertThat(compilerMessageCheck.getKind(), Matchers.is(Diagnostic.Kind.ERROR)); - MatcherAssert.assertThat(compilerMessageCheck.getLineNumber(), Matchers.is(5L)); - MatcherAssert.assertThat(compilerMessageCheck.getColumnNumber(), Matchers.is(6L)); - MatcherAssert.assertThat(compilerMessageCheck.getLocale(), Matchers.is(Locale.ENGLISH)); - MatcherAssert.assertThat(compilerMessageCheck.getComparisonKind(), Matchers.is(CompileTestConfiguration.ComparisonKind.CONTAINS)); - MatcherAssert.assertThat(compilerMessageCheck.getExpectedMessage(), Matchers.is("ABC")); + CuteApi.CompilerTestBB configuration = CompileTestBuilder.compilationTest().expectErrorMessage().atSource("XYZ").atLineNumber(5L).atColumnNumber(6L).withLocale(Locale.ENGLISH).thatContains("ABC").createCompileTestConfiguration(); + CuteApi.CompilerMessageCheckBB compilerMessageCheck = configuration.compilerMessageChecks().iterator().next(); + MatcherAssert.assertThat(compilerMessageCheck.atSource(), Matchers.is("XYZ")); + MatcherAssert.assertThat(compilerMessageCheck.getKind(), Matchers.is(CuteApi.CompilerMessageKind.ERROR)); + MatcherAssert.assertThat(compilerMessageCheck.atLine(), Matchers.is(5)); + MatcherAssert.assertThat(compilerMessageCheck.atColumn(), Matchers.is(6)); + MatcherAssert.assertThat(compilerMessageCheck.withLocale(), Matchers.is(Locale.ENGLISH)); + MatcherAssert.assertThat(compilerMessageCheck.getComparisonType(), Matchers.is(CuteApi.CompilerMessageComparisonType.CONTAINS)); + MatcherAssert.assertThat(compilerMessageCheck.getSearchString(), Matchers.contains("ABC")); } @@ -734,7 +741,7 @@ public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement el .executeTest(); } catch (AssertionError e) { - MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(String.format(Constants.Messages.UNIT_TEST_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT.getMessagePattern(), TestAnnotation.class.getCanonicalName()))); + MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(String.format(Constants.Messages.MESSAGE_PROCESSOR_HASNT_BEEN_APPLIED.getMessagePattern(), UnitTestAnnotationProcessorClass.class.getCanonicalName(), Arrays.asList(TestAnnotation.class.getCanonicalName())))); return; } @@ -758,7 +765,7 @@ public void unitTest(ProcessingEnvironment processingEnvironment, TypeElement el .executeTest(); } catch (AssertionError e) { - MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(String.format(Constants.Messages.UNIT_TEST_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT_WITH_PASSIN_ANNOTATION.getMessagePattern(), TestAnnotation.class.getCanonicalName()))); + MatcherAssert.assertThat(e.getMessage(), Matchers.containsString(String.format(Constants.Messages.UNIT_TEST_PRECONDITION_MUST_FIND_EXACTLY_ONE_ELEMENT_WITH_PASSIN_ANNOTATION.getMessagePattern(), PassIn.class.getCanonicalName(),PassIn.class.getCanonicalName()))); return; } @@ -858,7 +865,7 @@ public void test_passIn_withProcessorPassIn_withNonMatchingElementType() { try { CompileTestBuilder .unitTest() - .defineTestWithPassedInElement(SimpleTestProcessor1.class, PassInClass.class, new UnitTestForTestingAnnotationProcessors() { + .defineTestWithPassedInElement(SimpleTestProcessor1.class, PassInClass.class, new UnitTestForTestingAnnotationProcessors() { @Override public void unitTest(SimpleTestProcessor1 unit, ProcessingEnvironment processingEnvironment, ExecutableElement element) { throw new AssertionError("should have thrown assertion error!"); @@ -880,7 +887,7 @@ public void test_passIn_withProcessorPassIn_withMatchingElementButClassCastExcep CompileTestBuilder .unitTest() - .defineTestWithPassedInElement(SimpleTestProcessor1.class, PassInClass.class, new UnitTestForTestingAnnotationProcessors() { + .defineTestWithPassedInElement(SimpleTestProcessor1.class, PassInClass.class, new UnitTestForTestingAnnotationProcessors() { @Override public void unitTest(SimpleTestProcessor1 unit, ProcessingEnvironment processingEnvironment, Element element) { throw new ClassCastException("Test Class Cast Exception"); diff --git a/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestAnnotation1.java b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestAnnotation1.java new file mode 100644 index 0000000..62cd2f3 --- /dev/null +++ b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestAnnotation1.java @@ -0,0 +1,12 @@ +package io.toolisticon.cute.common; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface SimpleTestAnnotation1 { +} diff --git a/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestAnnotation2.java b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestAnnotation2.java new file mode 100644 index 0000000..fd663fa --- /dev/null +++ b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestAnnotation2.java @@ -0,0 +1,12 @@ +package io.toolisticon.cute.common; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface SimpleTestAnnotation2 { +} diff --git a/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestAnnotation3.java b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestAnnotation3.java new file mode 100644 index 0000000..47c62f2 --- /dev/null +++ b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestAnnotation3.java @@ -0,0 +1,13 @@ +package io.toolisticon.cute.common; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface SimpleTestAnnotation3 { +} + diff --git a/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestProcessor1.java b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestProcessor1.java new file mode 100644 index 0000000..c4c2213 --- /dev/null +++ b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestProcessor1.java @@ -0,0 +1,29 @@ +package io.toolisticon.cute.common; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.TypeElement; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + + +public class SimpleTestProcessor1 extends AbstractProcessor { + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + return false; + } + + + @Override + public Set getSupportedAnnotationTypes() { + + return new HashSet(Arrays.asList(SimpleTestAnnotation1.class.getCanonicalName())); + + } + + public ProcessingEnvironment getProcessingEnvironment() { + return this.processingEnv; + } +} \ No newline at end of file diff --git a/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestProcessor2.java b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestProcessor2.java new file mode 100644 index 0000000..84d056d --- /dev/null +++ b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestProcessor2.java @@ -0,0 +1,22 @@ +package io.toolisticon.cute.common; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.TypeElement; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class SimpleTestProcessor2 extends AbstractProcessor { + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + return false; + } + + @Override + public Set getSupportedAnnotationTypes() { + + return new HashSet(Arrays.asList(SimpleTestAnnotation2.class.getCanonicalName())); + + } +} diff --git a/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestProcessor3.java b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestProcessor3.java new file mode 100644 index 0000000..c69871f --- /dev/null +++ b/legacy/src/test/java/io/toolisticon/cute/common/SimpleTestProcessor3.java @@ -0,0 +1,22 @@ +package io.toolisticon.cute.common; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.TypeElement; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class SimpleTestProcessor3 extends AbstractProcessor { + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + return false; + } + + @Override + public Set getSupportedAnnotationTypes() { + + return new HashSet(Arrays.asList(SimpleTestAnnotation3.class.getCanonicalName())); + + } +} diff --git a/legacy/src/test/resources/compiletests/TestClass.java b/legacy/src/test/resources/compiletests/TestClass.java new file mode 100644 index 0000000..32baade --- /dev/null +++ b/legacy/src/test/resources/compiletests/TestClass.java @@ -0,0 +1,6 @@ +package io.toolisticon.annotationprocessortoolkit.testhelper; + +public class TestClass { + +} + diff --git a/legacy/src/test/resources/compiletests/javafileobjectutilstest/JavaSourceFromResourceTestClass.java b/legacy/src/test/resources/compiletests/javafileobjectutilstest/JavaSourceFromResourceTestClass.java new file mode 100644 index 0000000..985d735 --- /dev/null +++ b/legacy/src/test/resources/compiletests/javafileobjectutilstest/JavaSourceFromResourceTestClass.java @@ -0,0 +1,7 @@ +package io.toolisticon.annotationprocessortoolkit.testhelper.compiletest; + +public class JavaSourceFromResourceTestClass { + + + +} \ No newline at end of file diff --git a/legacy/src/test/resources/compiletests/passintest/PassInTestClass.java b/legacy/src/test/resources/compiletests/passintest/PassInTestClass.java new file mode 100644 index 0000000..2461016 --- /dev/null +++ b/legacy/src/test/resources/compiletests/passintest/PassInTestClass.java @@ -0,0 +1,15 @@ +package io.toolisticon.annotationprocessortoolkit.testhelper.compiletest; + +import io.toolisticon.cute.PassIn; +import io.toolisticon.cute.TestAnnotation; + +@TestAnnotation +public class PassInTestClass { + + @PassIn + @TestAnnotation + public static class InnerTestClass { + + } + +} \ No newline at end of file diff --git a/legacy/src/test/resources/compiletests/passintest/PassInTestClassMultipleAnnotatedWithMultiplePassIn.java b/legacy/src/test/resources/compiletests/passintest/PassInTestClassMultipleAnnotatedWithMultiplePassIn.java new file mode 100644 index 0000000..f6d084a --- /dev/null +++ b/legacy/src/test/resources/compiletests/passintest/PassInTestClassMultipleAnnotatedWithMultiplePassIn.java @@ -0,0 +1,16 @@ +package io.toolisticon.annotationprocessortoolkit.testhelper.compiletest; + +import io.toolisticon.cute.PassIn; +import io.toolisticon.cute.TestAnnotation; + +@PassIn +@TestAnnotation +public class PassInTestClassMultipleAnnotatedWithMultiplePassIn { + + @PassIn + @TestAnnotation + public static class InnerTestClass { + + } + +} \ No newline at end of file diff --git a/legacy/src/test/resources/compiletests/passintest/PassInTestClassMultipleAnnotatedWithoutPassIn.java b/legacy/src/test/resources/compiletests/passintest/PassInTestClassMultipleAnnotatedWithoutPassIn.java new file mode 100644 index 0000000..75cfc40 --- /dev/null +++ b/legacy/src/test/resources/compiletests/passintest/PassInTestClassMultipleAnnotatedWithoutPassIn.java @@ -0,0 +1,14 @@ +package io.toolisticon.annotationprocessortoolkit.testhelper.compiletest; + +import io.toolisticon.cute.PassIn; +import io.toolisticon.cute.TestAnnotation; + +@PassIn +public class PassInTestClassMultipleAnnotatedWithoutPassIn { + + @PassIn + public static class InnerTestClass { + + } + +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index f21c4fa..94ba140 100644 --- a/pom.xml +++ b/pom.xml @@ -16,8 +16,10 @@ extension cute + legacy integration-test + coverage @@ -76,13 +78,14 @@ UTF-8 UTF-8 - 1.7 + 1.8 - 1.7 - 1.7 + 1.8 + 1.8 0.8.0 + 0.8.3 4.13.1 @@ -93,7 +96,7 @@ 2.28.2 - 1.17 + 1.18 4.3.0 0.8.8 2.4 @@ -156,6 +159,7 @@ io.toolisticon.cute:* + io.toolisticon.fluapigen:fluapigen-api:compile:* *:*:*:*:test:* *:*:*:*:provided:* @@ -432,7 +436,7 @@ - check_java17 + check_java18 test @@ -444,7 +448,7 @@ org.codehaus.mojo.signature - java17 + java18 1.0 @@ -501,7 +505,7 @@ org.codehaus.mojo.signature - java17 + java18 1.0 @@ -574,6 +578,33 @@ + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + ${sonatype-oss-dist-mgmt-snapshots-url} + + + sonatype-nexus-staging + Nexus Release Repository + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + @@ -630,6 +661,12 @@ ${spiap.version} provided + + io.toolisticon.fluapigen + fluapigen-api + ${fluapigen.version} + compile +