/* * Copyright 2014 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.inferred.freebuilder.processor.util.testing; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.google.common.collect.ImmutableSet; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.io.IOException; import java.io.Writer; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.SourceVersion; import javax.lang.model.element.TypeElement; /** Unit tests for {@link BehaviorTester}. */ @RunWith(JUnit4.class) public class BehaviorTesterTest { private final BehaviorTester behaviorTester = BehaviorTester.create(); @Test public void simpleExample() { behaviorTester .with(new SourceBuilder() .addLine("package com.example;") .addLine("@%s(%s.RUNTIME)", Retention.class, RetentionPolicy.class) .addLine("public @interface TestAnnotation { }") .build()) .with(new SourceBuilder() .addLine("package com.example;") .addLine("@TestAnnotation public class MyClass {") .addLine(" public MyOtherClass get() {") .addLine(" return new MyOtherClass();") .addLine(" }") .addLine("}") .build()) .with( new TestProcessor() { @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { if (!annotations.isEmpty()) { try (Writer writer = processingEnv.getFiler() .createSourceFile("com.example.MyOtherClass") .openWriter()) { writer.append("package com.example;\n" + "public class MyOtherClass {\n" + " public String get() {\n" + " return \"Hello world!\";\n" + " }\n" + "}\n"); } catch (IOException e) { throw new RuntimeException(e); } } return true; } }) .with(new TestBuilder() .addLine("assertEquals(\"Hello world!\", new com.example.MyClass().get().get());") .build()) .runTest(); } @Test public void failingTest_throwsOriginalRuntimeException() { boolean caughtError = false; try { behaviorTester .with(new TestBuilder() .addLine("assertEquals(2, 3);") .build()) .runTest(); } catch (AssertionError e) { caughtError = true; assertEquals("expected:<2> but was:<3>", e.getMessage()); } assertTrue("Expected an AssertionError", caughtError); } @Test(expected = CompilationException.class) public void failingCompilation_throwsAssertionError() { behaviorTester .with(new TestBuilder() .addLine("jooblefish") .build()) .runTest(); } @Test public void failingTest_includesHelpfulStackTrace() { int firstLine = new Exception().getStackTrace()[0].getLineNumber(); try { behaviorTester .with(new TestBuilder() .addLine("throw new RuntimeException(\"d'oh\");") // 4 lines after firstLine .build()) .runTest(); fail("Expected RuntimeException"); } catch (RuntimeException e) { assertEquals("d'oh", e.getMessage()); StackTraceElement stackTraceElement = e.getStackTrace()[0]; assertThat(stackTraceElement.getClassName()).contains( "org.inferred.freebuilder.processor.util.testing.generatedcode.BehaviorTesterTest"); assertEquals("failingTest_includesHelpfulStackTrace", stackTraceElement.getMethodName()); assertTrue( (stackTraceElement.getLineNumber() == firstLine + 4) // ECJ gives great stack traces || (stackTraceElement.getLineNumber() == firstLine + 2)); // javac, not so great } } private abstract static class TestProcessor extends AbstractProcessor { @Override public Set<String> getSupportedAnnotationTypes() { return ImmutableSet.of("com.example.TestAnnotation"); } @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); } } }