| /* |
| * 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.value; |
| |
| import com.google.auto.value.annotations.Empty; |
| import com.google.auto.value.annotations.GwtArrays; |
| import com.google.auto.value.annotations.StringValues; |
| import com.google.common.collect.ImmutableCollection; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.ImmutableSortedSet; |
| import com.google.common.primitives.Ints; |
| import com.google.common.testing.EqualsTester; |
| import java.lang.annotation.Annotation; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.SortedSet; |
| import java.util.TreeSet; |
| import junit.framework.TestCase; |
| |
| /** |
| * @author emcmanus@google.com (Éamonn McManus) |
| */ |
| public class AutoAnnotationTest extends TestCase { |
| @AutoAnnotation private static StringValues newStringValues(String[] value) { |
| return new AutoAnnotation_AutoAnnotationTest_newStringValues(value); |
| } |
| |
| @Empty |
| @StringValues("oops") |
| class AnnotatedClass {} |
| |
| public void testSimple() { |
| StringValues expectedStringValues = AnnotatedClass.class.getAnnotation(StringValues.class); |
| StringValues actualStringValues = newStringValues(new String[] {"oops"}); |
| StringValues otherStringValues = newStringValues(new String[] {}); |
| new EqualsTester() |
| .addEqualityGroup(expectedStringValues, actualStringValues) |
| .addEqualityGroup(otherStringValues) |
| .testEquals(); |
| } |
| |
| public void testArraysAreCloned() { |
| String[] array = {"Jekyll"}; |
| StringValues stringValues = newStringValues(array); |
| array[0] = "Hyde"; |
| assertEquals("Jekyll", stringValues.value()[0]); |
| stringValues.value()[0] = "Hyde"; |
| assertEquals("Jekyll", stringValues.value()[0]); |
| } |
| |
| public void testGwtArraysAreCloned() { |
| String[] strings = {"Jekyll"}; |
| int[] ints = {2, 3, 5}; |
| GwtArrays arrays = newGwtArrays(strings, ints); |
| assertEquals(ImmutableList.of("Jekyll"), ImmutableList.copyOf(arrays.strings())); |
| assertEquals(ImmutableList.of(2, 3, 5), Ints.asList(arrays.ints())); |
| strings[0] = "Hyde"; |
| ints[0] = -1; |
| assertEquals(ImmutableList.of("Jekyll"), ImmutableList.copyOf(arrays.strings())); |
| assertEquals(ImmutableList.of(2, 3, 5), Ints.asList(arrays.ints())); |
| } |
| |
| @AutoAnnotation private static GwtArrays newGwtArrays(String[] strings, int[] ints) { |
| return new AutoAnnotation_AutoAnnotationTest_newGwtArrays(strings, ints); |
| } |
| |
| @AutoAnnotation private static StringValues newStringValuesVarArgs(String... value) { |
| return new AutoAnnotation_AutoAnnotationTest_newStringValuesVarArgs(value); |
| } |
| |
| public void testSimpleVarArgs() { |
| StringValues expectedStringValues = AnnotatedClass.class.getAnnotation(StringValues.class); |
| StringValues actualStringValues = newStringValuesVarArgs("oops"); |
| StringValues otherStringValues = newStringValuesVarArgs(new String[] {}); |
| new EqualsTester() |
| .addEqualityGroup(expectedStringValues, actualStringValues) |
| .addEqualityGroup(otherStringValues) |
| .testEquals(); |
| } |
| |
| @AutoAnnotation private static Empty newEmpty() { |
| return new AutoAnnotation_AutoAnnotationTest_newEmpty(); |
| } |
| |
| public void testEmpty() { |
| Empty expectedEmpty = AnnotatedClass.class.getAnnotation(Empty.class); |
| Empty actualEmpty = newEmpty(); |
| new EqualsTester() |
| .addEqualityGroup(expectedEmpty, actualEmpty) |
| .testEquals(); |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface Everything { |
| byte aByte(); |
| short aShort(); |
| int anInt(); |
| long aLong(); |
| float aFloat(); |
| double aDouble(); |
| char aChar(); |
| boolean aBoolean(); |
| String aString(); |
| RetentionPolicy anEnum(); |
| StringValues anAnnotation(); |
| byte[] bytes(); |
| short[] shorts(); |
| int[] ints(); |
| long[] longs(); |
| float[] floats(); |
| double[] doubles(); |
| char[] chars(); |
| boolean[] booleans(); |
| String[] strings(); |
| RetentionPolicy[] enums(); |
| StringValues[] annotations(); |
| } |
| |
| @AutoAnnotation static Everything newEverything( |
| byte aByte, |
| short aShort, |
| int anInt, |
| long aLong, |
| float aFloat, |
| double aDouble, |
| char aChar, |
| boolean aBoolean, |
| String aString, |
| RetentionPolicy anEnum, |
| StringValues anAnnotation, |
| byte[] bytes, |
| short[] shorts, |
| int[] ints, |
| long[] longs, |
| float[] floats, |
| double[] doubles, |
| char[] chars, |
| boolean[] booleans, |
| String[] strings, |
| RetentionPolicy[] enums, |
| StringValues[] annotations) { |
| return new AutoAnnotation_AutoAnnotationTest_newEverything( |
| aByte, aShort, anInt, aLong, aFloat, aDouble, aChar, aBoolean, aString, anEnum, |
| anAnnotation, bytes, shorts, ints, longs, floats, doubles, chars, booleans, strings, enums, |
| annotations); |
| } |
| |
| @AutoAnnotation static Everything newEverythingCollections( |
| byte aByte, |
| short aShort, |
| int anInt, |
| long aLong, |
| float aFloat, |
| double aDouble, |
| char aChar, |
| boolean aBoolean, |
| String aString, |
| RetentionPolicy anEnum, |
| StringValues anAnnotation, |
| Collection<Byte> bytes, |
| List<Short> shorts, |
| ArrayList<Integer> ints, |
| Set<Long> longs, |
| SortedSet<Float> floats, |
| TreeSet<Double> doubles, |
| LinkedHashSet<Character> chars, |
| ImmutableCollection<Boolean> booleans, |
| ImmutableList<String> strings, |
| ImmutableSet<RetentionPolicy> enums, |
| Set<StringValues> annotations) { |
| return new AutoAnnotation_AutoAnnotationTest_newEverythingCollections( |
| aByte, aShort, anInt, aLong, aFloat, aDouble, aChar, aBoolean, aString, anEnum, |
| anAnnotation, bytes, shorts, ints, longs, floats, doubles, chars, booleans, strings, enums, |
| annotations); |
| } |
| |
| @Everything( |
| aByte = 1, |
| aShort = 2, |
| anInt = 3, |
| aLong = -4, |
| aFloat = Float.NaN, |
| aDouble = Double.NaN, |
| aChar = '#', |
| aBoolean = true, |
| aString = "maybe\nmaybe not\n", |
| anEnum = RetentionPolicy.RUNTIME, |
| anAnnotation = @StringValues("whatever"), |
| bytes = {5, 6}, |
| shorts = {}, |
| ints = {7}, |
| longs = {8, 9}, |
| floats = {10, 11}, |
| doubles = {Double.NEGATIVE_INFINITY, -12.0, Double.POSITIVE_INFINITY}, |
| chars = {'?', '!', '\n'}, |
| booleans = {false, true, false}, |
| strings = {"ver", "vers", "vert", "verre", "vair"}, |
| enums = {RetentionPolicy.CLASS, RetentionPolicy.RUNTIME}, |
| annotations = { |
| @StringValues({}), @StringValues({"foo", "bar"}) |
| } |
| ) |
| private static class AnnotatedWithEverything {} |
| |
| // Get an instance of @Everything via reflection on the class AnnotatedWithEverything, |
| // fabricate an instance using newEverything that is supposed to be equal to it, and |
| // fabricate another instance using newEverything that is supposed to be different. |
| private static final Everything EVERYTHING_FROM_REFLECTION = |
| AnnotatedWithEverything.class.getAnnotation(Everything.class); |
| private static final Everything EVERYTHING_FROM_AUTO = newEverything( |
| (byte) 1, (short) 2, 3, -4, Float.NaN, Double.NaN, '#', true, |
| "maybe\nmaybe not\n", |
| RetentionPolicy.RUNTIME, |
| newStringValues(new String[] {"whatever"}), |
| new byte[] {5, 6}, |
| new short[] {}, |
| new int[] {7}, |
| new long[] {8, 9}, |
| new float[] {10, 11}, |
| new double[] {Double.NEGATIVE_INFINITY, -12.0, Double.POSITIVE_INFINITY}, |
| new char[] {'?', '!', '\n'}, |
| new boolean[] {false, true, false}, |
| new String[] {"ver", "vers", "vert", "verre", "vair"}, |
| new RetentionPolicy[] {RetentionPolicy.CLASS, RetentionPolicy.RUNTIME}, |
| new StringValues[] { |
| newStringValues(new String[] {}), |
| newStringValues(new String[] {"foo", "bar"}), |
| }); |
| private static final Everything EVERYTHING_FROM_AUTO_COLLECTIONS = newEverythingCollections( |
| (byte) 1, (short) 2, 3, -4, Float.NaN, Double.NaN, '#', true, |
| "maybe\nmaybe not\n", |
| RetentionPolicy.RUNTIME, |
| newStringValues(new String[] {"whatever"}), |
| Arrays.asList((byte) 5, (byte) 6), |
| Collections.<Short>emptyList(), |
| new ArrayList<Integer>(Collections.singleton(7)), |
| ImmutableSet.of(8L, 9L), |
| ImmutableSortedSet.of(10f, 11f), |
| new TreeSet<Double>( |
| ImmutableList.of(Double.NEGATIVE_INFINITY, -12.0, Double.POSITIVE_INFINITY)), |
| new LinkedHashSet<Character>(ImmutableList.of('?', '!', '\n')), |
| ImmutableList.of(false, true, false), |
| ImmutableList.of("ver", "vers", "vert", "verre", "vair"), |
| ImmutableSet.of(RetentionPolicy.CLASS, RetentionPolicy.RUNTIME), |
| ImmutableSet.of( |
| newStringValues(new String[] {}), |
| newStringValues(new String[] {"foo", "bar"}))); |
| private static final Everything EVERYTHING_ELSE_FROM_AUTO = newEverything( |
| (byte) 0, (short) 0, 0, 0, 0, 0, '0', false, "", RetentionPolicy.SOURCE, |
| newStringValues(new String[] {""}), |
| new byte[0], new short[0], new int[0], new long[0], new float[0], new double[0], |
| new char[0], new boolean[0], new String[0], new RetentionPolicy[0], new StringValues[0]); |
| private static final Everything EVERYTHING_ELSE_FROM_AUTO_COLLECTIONS = newEverythingCollections( |
| (byte) 0, (short) 0, 0, 0, 0, 0, '0', false, "", RetentionPolicy.SOURCE, |
| newStringValues(new String[] {""}), |
| ImmutableList.<Byte>of(), |
| Collections.<Short>emptyList(), |
| new ArrayList<Integer>(), |
| Collections.<Long>emptySet(), |
| ImmutableSortedSet.<Float>of(), |
| new TreeSet<Double>(), |
| new LinkedHashSet<Character>(), |
| ImmutableSet.<Boolean>of(), |
| ImmutableList.<String>of(), |
| ImmutableSet.<RetentionPolicy>of(), |
| Collections.<StringValues>emptySet()); |
| |
| public void testEqualsAndHashCode() { |
| new EqualsTester() |
| .addEqualityGroup( |
| EVERYTHING_FROM_REFLECTION, EVERYTHING_FROM_AUTO, EVERYTHING_FROM_AUTO_COLLECTIONS) |
| .addEqualityGroup(EVERYTHING_ELSE_FROM_AUTO, EVERYTHING_ELSE_FROM_AUTO_COLLECTIONS) |
| .testEquals(); |
| } |
| |
| public static class IntList extends ArrayList<Integer> { |
| IntList(Collection<Integer> c) { |
| super(c); |
| } |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface IntArray { |
| int[] ints(); |
| } |
| |
| @IntArray(ints = {1, 2, 3}) |
| private static class AnnotatedWithIntArray {} |
| |
| @AutoAnnotation static IntArray newIntArray(IntList ints) { |
| return new AutoAnnotation_AutoAnnotationTest_newIntArray(ints); |
| } |
| |
| /** |
| * Test that we can represent a primitive array member with a parameter whose type is a |
| * collection of the corresponding wrapper type, even if the wrapper type is not explicitly a type |
| * parameter. Specifically, if the member is an {@code int[]} then obviously we can represent it |
| * as a {@code List<Integer>}, but here we test that we can also represent it as an {@code |
| * IntList}, which is only a {@code List<Integer>} by virtue of inheritance. This is a separate |
| * test rather than just putting an {@code IntList} parameter into {@link |
| * #newEverythingCollections} because we want to check that we are still able to detect the |
| * primitive wrapper type even though it's hidden in this way. We need to generate a helper method |
| * for every primitive wrapper. |
| */ |
| public void testDerivedPrimitiveCollection() { |
| IntList intList = new IntList(ImmutableList.of(1, 2, 3)); |
| IntArray actual = newIntArray(intList); |
| IntArray expected = AnnotatedWithIntArray.class.getAnnotation(IntArray.class); |
| assertEquals(expected, actual); |
| } |
| |
| public void testToString() { |
| String expected = "@com.google.auto.value.AutoAnnotationTest.Everything(" |
| + "aByte=1, aShort=2, anInt=3, aLong=-4, aFloat=NaN, aDouble=NaN, aChar='#', " |
| + "aBoolean=true, aString=\"maybe\\nmaybe not\\n\", anEnum=RUNTIME, " |
| + "anAnnotation=@com.google.auto.value.annotations.StringValues([\"whatever\"]), " |
| + "bytes=[5, 6], shorts=[], ints=[7], longs=[8, 9], floats=[10.0, 11.0], " |
| + "doubles=[-Infinity, -12.0, Infinity], " |
| + "chars=['?', '!', '\\n'], " |
| + "booleans=[false, true, false], " |
| + "strings=[\"ver\", \"vers\", \"vert\", \"verre\", \"vair\"], " |
| + "enums=[CLASS, RUNTIME], " |
| + "annotations=[" |
| + "@com.google.auto.value.annotations.StringValues([]), " |
| + "@com.google.auto.value.annotations.StringValues([\"foo\", \"bar\"])" |
| + "]" |
| + ")"; |
| assertEquals(expected, EVERYTHING_FROM_AUTO.toString()); |
| assertEquals(expected, EVERYTHING_FROM_AUTO_COLLECTIONS.toString()); |
| } |
| |
| public void testStringQuoting() { |
| StringValues instance = newStringValues( |
| new String[] { |
| "", |
| "\r\n", |
| "hello, world", |
| "Éamonn", |
| "\007\uffef", |
| }); |
| String expected = "@com.google.auto.value.annotations.StringValues(" |
| + "[\"\", \"\\r\\n\", \"hello, world\", \"Éamonn\", \"\\007\\uffef\"])"; |
| assertEquals(expected, instance.toString()); |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface AnnotationsAnnotation { |
| Class<? extends Annotation>[] value(); |
| } |
| |
| @AnnotationsAnnotation(AnnotationsAnnotation.class) |
| static class AnnotatedWithAnnotationsAnnotation {} |
| |
| @AutoAnnotation static AnnotationsAnnotation newAnnotationsAnnotation( |
| List<Class<? extends Annotation>> value) { |
| return new AutoAnnotation_AutoAnnotationTest_newAnnotationsAnnotation(value); |
| } |
| |
| public void testGenericArray() { |
| AnnotationsAnnotation generated = |
| newAnnotationsAnnotation( |
| ImmutableList.<Class<? extends Annotation>>of(AnnotationsAnnotation.class)); |
| AnnotationsAnnotation fromReflect = |
| AnnotatedWithAnnotationsAnnotation.class.getAnnotation(AnnotationsAnnotation.class); |
| assertEquals(fromReflect, generated); |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @interface ClassesAnnotation { |
| Class<?>[] value(); |
| } |
| |
| @ClassesAnnotation(AnnotationsAnnotation.class) |
| static class AnnotatedWithClassesAnnotation {} |
| |
| @AutoAnnotation static ClassesAnnotation newClassesAnnotation( |
| List<Class<?>> value) { |
| return new AutoAnnotation_AutoAnnotationTest_newClassesAnnotation(value); |
| } |
| |
| public void testWildcardArray() { |
| ClassesAnnotation generated = |
| newClassesAnnotation( |
| Arrays.<Class<?>>asList(AnnotationsAnnotation.class)); |
| ClassesAnnotation fromReflect = |
| AnnotatedWithClassesAnnotation.class.getAnnotation(ClassesAnnotation.class); |
| assertEquals(fromReflect, generated); |
| } |
| } |