aboutsummaryrefslogtreecommitdiff
path: root/common/src/test/java/com
diff options
context:
space:
mode:
authorcgruber <cgruber@google.com>2015-01-08 17:26:12 -0800
committerChristian Edward Gruber <cgruber@google.com>2015-01-21 13:43:13 -0800
commitd1f1f9a1c13a9ab76db20380ad6479da2af88bc6 (patch)
tree0cdc34af9f36843179e4518da412668af3a584fd /common/src/test/java/com
parente8fb2085e8686100b205e1698e4a249eadea69d9 (diff)
downloadauto-d1f1f9a1c13a9ab76db20380ad6479da2af88bc6.tar.gz
Add AnnotationMirrors, AnnotationValues, and a BasicAnnotationProcessor which performs early validation of elements, and stores un-processable elements and re-tries them on subsequent processing rounds (in case the processor depends on code which will become valid in future rounds). Also, move some stray tests from dagger to google/auto common.
------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83567228
Diffstat (limited to 'common/src/test/java/com')
-rw-r--r--common/src/test/java/com/google/auto/common/AnnotationMirrorsTest.java214
-rw-r--r--common/src/test/java/com/google/auto/common/BasicAnnotationProcessorTest.java184
-rw-r--r--common/src/test/java/com/google/auto/common/MoreElementsTest.java46
-rw-r--r--common/src/test/java/com/google/auto/common/MoreTypesIsTypeOfTest.java4
4 files changed, 431 insertions, 17 deletions
diff --git a/common/src/test/java/com/google/auto/common/AnnotationMirrorsTest.java b/common/src/test/java/com/google/auto/common/AnnotationMirrorsTest.java
new file mode 100644
index 00000000..2f7fef14
--- /dev/null
+++ b/common/src/test/java/com/google/auto/common/AnnotationMirrorsTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 com.google.auto.common;
+
+import static com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.BLAH;
+import static com.google.auto.common.AnnotationMirrorsTest.SimpleEnum.FOO;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
+import com.google.common.testing.EquivalenceTester;
+import com.google.testing.compile.CompilationRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Map;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.SimpleAnnotationValueVisitor6;
+
+/**
+ * Tests {@link AnnotationMirrors}.
+ */
+@RunWith(JUnit4.class)
+public class AnnotationMirrorsTest {
+ @Rule public CompilationRule compilationRule = new CompilationRule();
+
+ private Elements elements;
+
+ @Before public void setUp() {
+ this.elements = compilationRule.getElements();
+ }
+
+ @interface SimpleAnnotation {}
+
+ @SimpleAnnotation class SimplyAnnotated {}
+ @SimpleAnnotation class AlsoSimplyAnnotated {}
+
+ enum SimpleEnum {
+ BLAH, FOO
+ }
+
+ @interface Outer {
+ SimpleEnum value();
+ }
+
+ @Outer(BLAH) static class TestClassBlah {}
+ @Outer(BLAH) static class TestClassBlah2 {}
+ @Outer(FOO) static class TestClassFoo {}
+
+ @interface DefaultingOuter {
+ SimpleEnum value() default SimpleEnum.BLAH;
+ }
+
+ @DefaultingOuter class TestWithDefaultingOuterDefault {}
+ @DefaultingOuter(BLAH) class TestWithDefaultingOuterBlah {}
+ @DefaultingOuter(FOO) class TestWithDefaultingOuterFoo {}
+
+ @interface AnnotatedOuter {
+ DefaultingOuter value();
+ }
+
+ @AnnotatedOuter(@DefaultingOuter) class TestDefaultNestedAnnotated {}
+ @AnnotatedOuter(@DefaultingOuter(BLAH)) class TestBlahNestedAnnotated {}
+ @AnnotatedOuter(@DefaultingOuter(FOO)) class TestFooNestedAnnotated {}
+
+ @interface OuterWithValueArray {
+ DefaultingOuter[] value() default {};
+ }
+
+ @OuterWithValueArray class TestValueArrayWithDefault {}
+ @OuterWithValueArray({}) class TestValueArrayWithEmpty {}
+
+ @OuterWithValueArray({@DefaultingOuter}) class TestValueArrayWithOneDefault {}
+ @OuterWithValueArray(@DefaultingOuter(BLAH)) class TestValueArrayWithOneBlah {}
+ @OuterWithValueArray(@DefaultingOuter(FOO)) class TestValueArrayWithOneFoo {}
+
+ @OuterWithValueArray({@DefaultingOuter(FOO), @DefaultingOuter})
+ class TestValueArrayWithFooAndDefaultBlah {}
+ @OuterWithValueArray({@DefaultingOuter(FOO), @DefaultingOuter(BLAH)})
+ class TestValueArrayWithFooBlah {}
+ @OuterWithValueArray({@DefaultingOuter(FOO), @DefaultingOuter(BLAH)})
+ class TestValueArrayWithFooBlah2 {} // Different instances than on TestValueArrayWithFooBlah.
+ @OuterWithValueArray({@DefaultingOuter(BLAH), @DefaultingOuter(FOO)})
+ class TestValueArrayWithBlahFoo {}
+
+ @Test public void testEquivalences() {
+ EquivalenceTester<AnnotationMirror> tester =
+ EquivalenceTester.of(AnnotationMirrors.equivalence());
+
+ tester.addEquivalenceGroup(
+ annotationOn(SimplyAnnotated.class),
+ annotationOn(AlsoSimplyAnnotated.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestClassBlah.class),
+ annotationOn(TestClassBlah2.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestClassFoo.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestWithDefaultingOuterDefault.class),
+ annotationOn(TestWithDefaultingOuterBlah.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestWithDefaultingOuterFoo.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestDefaultNestedAnnotated.class),
+ annotationOn(TestBlahNestedAnnotated.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestFooNestedAnnotated.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestValueArrayWithDefault.class),
+ annotationOn(TestValueArrayWithEmpty.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestValueArrayWithOneDefault.class),
+ annotationOn(TestValueArrayWithOneBlah.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestValueArrayWithOneFoo.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestValueArrayWithFooAndDefaultBlah.class),
+ annotationOn(TestValueArrayWithFooBlah.class),
+ annotationOn(TestValueArrayWithFooBlah2.class));
+
+ tester.addEquivalenceGroup(
+ annotationOn(TestValueArrayWithBlahFoo.class));
+
+ tester.test();
+ }
+
+ @interface Stringy {
+ String value() default "default";
+ }
+
+ @Stringy class StringyUnset {}
+ @Stringy("foo") class StringySet {}
+
+ @Test public void testGetDefaultValuesUnset() {
+ assertThat(annotationOn(StringyUnset.class).getElementValues()).isEmpty();
+ Iterable<AnnotationValue> values = AnnotationMirrors.getAnnotationValuesWithDefaults(
+ annotationOn(StringyUnset.class)).values();
+ String value = getOnlyElement(values).accept(new SimpleAnnotationValueVisitor6<String, Void>() {
+ @Override public String visitString(String value, Void ignored) {
+ return value;
+ }
+ }, null);
+ assertThat(value).isEqualTo("default");
+ }
+
+ @Test public void testGetDefaultValuesSet() {
+ Iterable<AnnotationValue> values = AnnotationMirrors.getAnnotationValuesWithDefaults(
+ annotationOn(StringySet.class)).values();
+ String value = getOnlyElement(values).accept(new SimpleAnnotationValueVisitor6<String, Void>() {
+ @Override public String visitString(String value, Void ignored) {
+ return value;
+ }
+ }, null);
+ assertThat(value).isEqualTo("foo");
+ }
+
+ @Test public void testGetValueEntry() {
+ Map.Entry<ExecutableElement, AnnotationValue> elementValue =
+ AnnotationMirrors.getAnnotationElementAndValue(
+ annotationOn(TestClassBlah.class), "value");
+ assertThat(elementValue.getKey().getSimpleName().toString()).isEqualTo("value");
+ assertThat(elementValue.getValue().getValue()).isInstanceOf(VariableElement.class);
+ AnnotationValue value = AnnotationMirrors.getAnnotationValue(
+ annotationOn(TestClassBlah.class), "value");
+ assertThat(value.getValue()).isInstanceOf(VariableElement.class);
+ }
+
+ @Test public void testGetValueEntryFailure() {
+ try {
+ AnnotationMirrors.getAnnotationValue(annotationOn(TestClassBlah.class), "a");
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage(
+ "@com.google.auto.common.AnnotationMirrorsTest.Outer does not define an element a()");
+ return;
+ }
+ fail("Should have thrown.");
+ }
+
+ private AnnotationMirror annotationOn(Class<?> clazz) {
+ return getOnlyElement(elements.getTypeElement(clazz.getCanonicalName()).getAnnotationMirrors());
+ }
+}
diff --git a/common/src/test/java/com/google/auto/common/BasicAnnotationProcessorTest.java b/common/src/test/java/com/google/auto/common/BasicAnnotationProcessorTest.java
new file mode 100644
index 00000000..0fd41c82
--- /dev/null
+++ b/common/src/test/java/com/google/auto/common/BasicAnnotationProcessorTest.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * 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 com.google.auto.common;
+
+import static com.google.common.truth.Truth.assertAbout;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.SetMultimap;
+import com.google.testing.compile.JavaFileObjects;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Set;
+
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
+
+@RunWith(JUnit4.class)
+public class BasicAnnotationProcessorTest {
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RequiresGeneratedCode {}
+
+ /** Asserts that the code generated by {@link GeneratesCode} and its processor is present. */
+ public static class RequiresGeneratedCodeProcessor extends BasicAnnotationProcessor {
+ boolean processed = false;
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latestSupported();
+ }
+
+ @Override
+ protected Iterable<? extends ProcessingStep> initSteps() {
+ return ImmutableSet.of(new ProcessingStep() {
+ @Override
+ public void process(
+ SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
+ processed = true;
+ try {
+ processingEnv.getFiler()
+ .getResource(StandardLocation.SOURCE_OUTPUT, "test", "SomeGeneratedClass");
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ @Override
+ public Set<? extends Class<? extends Annotation>> annotations() {
+ return ImmutableSet.of(RequiresGeneratedCode.class);
+ }
+ });
+ }
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface GeneratesCode {}
+
+ /** Generates a class called {@code test.SomeGeneratedClass}. */
+ public static class GeneratesCodeProcessor extends BasicAnnotationProcessor {
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latestSupported();
+ }
+
+ @Override
+ protected Iterable<? extends ProcessingStep> initSteps() {
+ return ImmutableSet.of(new ProcessingStep() {
+ @Override
+ public void process(
+ SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
+ for (Element element : elementsByAnnotation.values()) {
+ try {
+ generateClass(element);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ public Set<? extends Class<? extends Annotation>> annotations() {
+ return ImmutableSet.of(GeneratesCode.class);
+ }
+ });
+ }
+
+ private void generateClass(Element sourceType) throws IOException {
+ JavaFileObject source =
+ processingEnv.getFiler().createSourceFile("test.SomeGeneratedClass", sourceType);
+ PrintWriter writer = new PrintWriter(source.openWriter());
+ writer.println("package test;");
+ writer.println("public class SomeGeneratedClass {}");
+ writer.close();
+ }
+ }
+
+ @Test public void properlyDefersProcessing_typeElement() {
+ JavaFileObject classAFileObject = JavaFileObjects.forSourceLines("test.ClassA",
+ "package test;",
+ "",
+ "@" + RequiresGeneratedCode.class.getCanonicalName(),
+ "public class ClassA {",
+ " SomeGeneratedClass sgc;",
+ "}");
+ JavaFileObject classBFileObject = JavaFileObjects.forSourceLines("test.ClassB",
+ "package test;",
+ "",
+ "@" + GeneratesCode.class.getCanonicalName(),
+ "public class ClassB {}");
+ RequiresGeneratedCodeProcessor requiresGeneratedCodeProcessor =
+ new RequiresGeneratedCodeProcessor();
+ assertAbout(javaSources())
+ .that(ImmutableList.of(classAFileObject, classBFileObject))
+ .processedWith(requiresGeneratedCodeProcessor, new GeneratesCodeProcessor())
+ .compilesWithoutError();
+ assertThat(requiresGeneratedCodeProcessor.processed).isTrue();
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ReferencesAClass {
+ Class<?> value();
+ }
+
+ @Test public void properlyDefersProcessing_packageElement() {
+ JavaFileObject classAFileObject = JavaFileObjects.forSourceLines("test.ClassA",
+ "package test;",
+ "",
+ "@" + GeneratesCode.class.getCanonicalName(),
+ "public class ClassA {",
+ "}");
+ JavaFileObject packageFileObject = JavaFileObjects.forSourceLines("test.package-info",
+ "@" + RequiresGeneratedCode.class.getCanonicalName(),
+ "@" + ReferencesAClass.class.getCanonicalName() + "(SomeGeneratedClass.class)",
+ "package test;");
+ RequiresGeneratedCodeProcessor requiresGeneratedCodeProcessor =
+ new RequiresGeneratedCodeProcessor();
+ assertAbout(javaSources())
+ .that(ImmutableList.of(classAFileObject, packageFileObject))
+ .processedWith(requiresGeneratedCodeProcessor, new GeneratesCodeProcessor())
+ .compilesWithoutError();
+ assertThat(requiresGeneratedCodeProcessor.processed).isTrue();
+ }
+
+ @Test public void reportsMissingType() {
+ JavaFileObject classAFileObject = JavaFileObjects.forSourceLines("test.ClassA",
+ "package test;",
+ "",
+ "@" + RequiresGeneratedCode.class.getCanonicalName(),
+ "public class ClassA {",
+ " SomeGeneratedClass bar;",
+ "}");
+ assertAbout(javaSources())
+ .that(ImmutableList.of(classAFileObject))
+ .processedWith(new RequiresGeneratedCodeProcessor())
+ .failsToCompile()
+ .withErrorContaining(RequiresGeneratedCodeProcessor.class.getCanonicalName())
+ .in(classAFileObject).onLine(4);
+ }
+}
diff --git a/common/src/test/java/com/google/auto/common/MoreElementsTest.java b/common/src/test/java/com/google/auto/common/MoreElementsTest.java
index dffa89e2..ba1fc172 100644
--- a/common/src/test/java/com/google/auto/common/MoreElementsTest.java
+++ b/common/src/test/java/com/google/auto/common/MoreElementsTest.java
@@ -15,7 +15,7 @@
*/
package com.google.auto.common;
-import static com.google.common.truth.Truth.assert_;
+import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import com.google.common.base.Optional;
@@ -34,6 +34,7 @@ import java.lang.annotation.RetentionPolicy;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
@@ -56,16 +57,16 @@ public class MoreElementsTest {
@Test
public void getPackage() {
- assert_().that(javaLangPackageElement).isEqualTo(javaLangPackageElement);
- assert_().that(MoreElements.getPackage(stringElement)).isEqualTo(javaLangPackageElement);
+ assertThat(javaLangPackageElement).isEqualTo(javaLangPackageElement);
+ assertThat(MoreElements.getPackage(stringElement)).isEqualTo(javaLangPackageElement);
for (Element childElement : stringElement.getEnclosedElements()) {
- assert_().that(MoreElements.getPackage(childElement)).isEqualTo(javaLangPackageElement);
+ assertThat(MoreElements.getPackage(childElement)).isEqualTo(javaLangPackageElement);
}
}
@Test
public void asPackage() {
- assert_().that(MoreElements.asPackage(javaLangPackageElement))
+ assertThat(MoreElements.asPackage(javaLangPackageElement))
.isEqualTo(javaLangPackageElement);
}
@@ -77,9 +78,27 @@ public class MoreElementsTest {
} catch (IllegalArgumentException expected) {}
}
+ @Test public void asTypeElement() {
+ Element typeElement =
+ compilation.getElements().getTypeElement(String.class.getCanonicalName());
+ assertThat(MoreElements.asType(typeElement)).isEqualTo(typeElement);
+ }
+
+ @Test public void asTypeElement_notATypeElement() {
+ TypeElement typeElement =
+ compilation.getElements().getTypeElement(String.class.getCanonicalName());
+ for (ExecutableElement e : ElementFilter.methodsIn(typeElement.getEnclosedElements())) {
+ try {
+ MoreElements.asType(e);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+ }
+
@Test
public void asType() {
- assert_().that(MoreElements.asType(stringElement)).isEqualTo(stringElement);
+ assertThat(MoreElements.asType(stringElement)).isEqualTo(stringElement);
}
@Test
@@ -93,7 +112,7 @@ public class MoreElementsTest {
@Test
public void asVariable() {
for (Element variableElement : ElementFilter.fieldsIn(stringElement.getEnclosedElements())) {
- assert_().that(MoreElements.asVariable(variableElement)).isEqualTo(variableElement);
+ assertThat(MoreElements.asVariable(variableElement)).isEqualTo(variableElement);
}
}
@@ -108,11 +127,11 @@ public class MoreElementsTest {
@Test
public void asExecutable() {
for (Element methodElement : ElementFilter.methodsIn(stringElement.getEnclosedElements())) {
- assert_().that(MoreElements.asExecutable(methodElement)).isEqualTo(methodElement);
+ assertThat(MoreElements.asExecutable(methodElement)).isEqualTo(methodElement);
}
for (Element methodElement
: ElementFilter.constructorsIn(stringElement.getEnclosedElements())) {
- assert_().that(MoreElements.asExecutable(methodElement)).isEqualTo(methodElement);
+ assertThat(MoreElements.asExecutable(methodElement)).isEqualTo(methodElement);
}
}
@@ -135,14 +154,11 @@ public class MoreElementsTest {
public void isAnnotationPresent() {
TypeElement annotatedAnnotationElement =
compilation.getElements().getTypeElement(AnnotatedAnnotation.class.getCanonicalName());
- assert_()
- .that(MoreElements.isAnnotationPresent(annotatedAnnotationElement, Documented.class))
+ assertThat(MoreElements.isAnnotationPresent(annotatedAnnotationElement, Documented.class))
.isTrue();
- assert_()
- .that(MoreElements.isAnnotationPresent(annotatedAnnotationElement, InnerAnnotation.class))
+ assertThat(MoreElements.isAnnotationPresent(annotatedAnnotationElement, InnerAnnotation.class))
.isTrue();
- assert_()
- .that(MoreElements.isAnnotationPresent(annotatedAnnotationElement, SuppressWarnings.class))
+ assertThat(MoreElements.isAnnotationPresent(annotatedAnnotationElement, SuppressWarnings.class))
.isFalse();
}
diff --git a/common/src/test/java/com/google/auto/common/MoreTypesIsTypeOfTest.java b/common/src/test/java/com/google/auto/common/MoreTypesIsTypeOfTest.java
index b067f1e7..380b50a7 100644
--- a/common/src/test/java/com/google/auto/common/MoreTypesIsTypeOfTest.java
+++ b/common/src/test/java/com/google/auto/common/MoreTypesIsTypeOfTest.java
@@ -17,7 +17,7 @@ package com.google.auto.common;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assert_;
+import static org.junit.Assert.fail;
import com.google.common.collect.Iterables;
import com.google.testing.compile.CompilationRule;
@@ -164,7 +164,7 @@ public class MoreTypesIsTypeOfTest {
getOnlyElement(typeElementFor(DeclaredVoid.class).getEnclosedElements()).asType();
try {
MoreTypes.isTypeOf(String.class, method);
- assert_().fail();
+ fail();
} catch (IllegalArgumentException expected) {}
}