package retroweibo.processor;
import static com.google.common.truth.Truth.assert_;
import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
import com.google.common.collect.ImmutableList;
import com.google.testing.compile.JavaFileObjects;
import junit.framework.TestCase;
import java.util.List;
import javax.tools.JavaFileObject;
/**
* Tests to ensure annotations are kept on RetroWeibo generated classes
*
* @author jmcampanini
*/
public class PropertyAnnotationsTest extends TestCase {
private static final String PROPERTY_ANNOTATION_TEST =
"retroweibo.processor.PropertyAnnotationsTest";
private static final String TEST_ANNOTATION =
"@retroweibo.processor.PropertyAnnotationsTest.TestAnnotation";
public static enum TestEnum {
A, B;
@Override
public String toString() {
// used to prove that the method we determine the value does not use the `toString()` method
// of the enum
return "not the same value";
}
}
public static @interface TestAnnotation {
byte testByte() default 1;
short testShort() default 2;
int testInt() default 3;
long testLong() default 4L;
float testFloat() default 5.6f;
double testDouble() default 7.8d;
char testChar() default 'a';
String testString() default "10";
boolean testBoolean() default false;
Class<?> testClass() default TestEnum.class;
TestEnum testEnum() default TestEnum.A;
OtherAnnotation testAnnotation() default @OtherAnnotation(foo = 23, bar = "baz");
}
public static @interface OtherAnnotation {
int foo() default 123;
String bar() default "bar";
}
public static @interface TestAnnotationArray {
byte[] testBytes() default {1, 2};
short[] testShorts() default {3, 4};
int[] testInts() default {5, 6};
long[] testLongs() default {7L, 8L};
float[] testFloats() default {9.1f, 2.3f};
double[] testDoubles() default {4.5d, 6.7d};
char[] testChars() default {'a', 'b'};
String[] testStrings() default {"cde", "fgh"};
boolean[] testBooleans() default {true, false};
Class<?>[] testClasses() default {TestEnum.class, TestEnum.class};
TestEnum[] testEnums() default {TestEnum.A, TestEnum.B};
OtherAnnotation[] testAnnotations()
default {@OtherAnnotation(foo = 999), @OtherAnnotation(bar = "baz")};
}
private JavaFileObject sourceCode(List<String> imports, List<String> annotations) {
ImmutableList<String> list = ImmutableList.<String>builder()
.add(
"package foo.bar;",
"",
"import retroweibo.RetroWeibo;"
)
.addAll(imports)
.add(
"",
"@RetroWeibo",
"public abstract class Baz {"
)
.addAll(annotations)
.add(
" public abstract int buh();",
"",
" public static Baz create(int buh) {",
" return new RetroWeibo_Baz(buh);",
" }",
"}"
)
.build();
String[] lines = list.toArray(new String[list.size()]);
return JavaFileObjects.forSourceLines("foo.bar.Baz", lines);
}
private JavaFileObject expectedCode(List<String> annotations) {
ImmutableList<String> list = ImmutableList.<String>builder()
.add(
"package foo.bar;",
"",
"final class RetroWeibo_Baz extends Baz {",
" private final int buh;",
"",
" RetroWeibo_Baz(int buh) {",
" this.buh = buh;",
" }",
""
)
.addAll(annotations)
.add(
" @Override public int buh() {",
" return buh;",
" }",
"",
" @Override public String toString() {",
" return \"Baz{\"",
" + \"buh=\" + buh",
" + \"}\";",
" }",
"",
" @Override public boolean equals(Object o) {",
" if (o == this) {",
" return true;",
" }",
" if (o instanceof Baz) {",
" Baz that = (Baz) o;",
" return (this.buh == that.buh());",
" }",
" return false;",
" }",
"",
" @Override public int hashCode() {",
" int h = 1;",
" h *= 1000003;",
" h ^= buh;",
" return h;",
" }",
"}"
)
.build();
String[] lines = list.toArray(new String[list.size()]);
return JavaFileObjects.forSourceLines("foo.bar.RetroWeibo_Baz", lines);
}
private void assertGeneratedMatches(
List<String> imports,
List<String> annotations,
List<String> expectedAnnotations) {
JavaFileObject javaFileObject = sourceCode(imports, annotations);
JavaFileObject expectedOutput = expectedCode(expectedAnnotations);
assert_().about(javaSource())
.that(javaFileObject)
.processedWith(new RetroWeiboProcessor())
.compilesWithoutError()
.and().generatesSources(expectedOutput);
}
public void testSimpleAnnotation() {
assertGeneratedMatches(
ImmutableList.of("import javax.annotation.Nullable;"),
ImmutableList.of("@Nullable"),
ImmutableList.of("@javax.annotation.Nullable"));
}
public void testSingleStringValueAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of("@SuppressWarnings(\"a\")"),
ImmutableList.of("@java.lang.SuppressWarnings(value={\"a\"})"));
}
public void testMultiStringValueAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of("@SuppressWarnings({\"a\", \"b\"})"),
ImmutableList.of("@java.lang.SuppressWarnings(value={\"a\", \"b\"})"));
}
public void testNumberValueAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION + "(testShort = 1, testInt = 2, testLong = 3L)"),
ImmutableList.of(TEST_ANNOTATION + "(testShort = 1, testInt = 2, testLong = 3L)"));
}
public void testByteValueAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION + "(testByte = 0)"),
ImmutableList.of(TEST_ANNOTATION + "(testByte = 0)"));
}
public void testDecimalValueAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION + "(testDouble = 1.2d, testFloat = 3.4f)"),
ImmutableList.of(TEST_ANNOTATION + "(testDouble = 1.2d, testFloat = 3.4f)"));
}
public void testOtherValuesAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "(testBoolean = true, testString = \"hallo\", testChar = 'a')"),
ImmutableList.of(TEST_ANNOTATION
+ "(testBoolean = true, testString = \"hallo\", testChar = 'a')"));
}
public void testClassAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "(testClass = String.class)"),
ImmutableList.of(TEST_ANNOTATION
+ "(testClass = java.lang.String.class)"));
}
public void testEnumAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "(testEnum = " + PROPERTY_ANNOTATION_TEST + ".TestEnum.A)"),
ImmutableList.of(TEST_ANNOTATION
+ "(testEnum = " + PROPERTY_ANNOTATION_TEST + ".TestEnum.A)"));
}
public void testEmptyAnnotationAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "(testAnnotation = @" + PROPERTY_ANNOTATION_TEST + ".OtherAnnotation)"),
ImmutableList.of(TEST_ANNOTATION
+ "(testAnnotation = @" + PROPERTY_ANNOTATION_TEST + ".OtherAnnotation)"));
}
public void testValuedAnnotationAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "(testAnnotation = @" + PROPERTY_ANNOTATION_TEST + ".OtherAnnotation(foo=999))"),
ImmutableList.of(TEST_ANNOTATION
+ "(testAnnotation = @" + PROPERTY_ANNOTATION_TEST + ".OtherAnnotation(foo=999))"));
}
public void testNumberArrayAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testShorts = {2, 3}, testInts = {4, 5}, testLongs = {6L, 7L})"),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testShorts = {2, 3}, testInts = {4, 5}, testLongs = {6L, 7L})"));
}
public void testByteArrayAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION + "Array(testBytes = {0, 1})"),
ImmutableList.of(TEST_ANNOTATION + "Array(testBytes = {0, 1})"));
}
public void testDecimalArrayAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testDoubles = {1.2d, 3.4d}, testFloats = {5.6f, 7.8f})"),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testDoubles = {1.2d, 3.4d}, testFloats = {5.6f, 7.8f})"));
}
public void testOtherArrayAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testBooleans = {false, false},"
+ " testStrings = {\"aaa\", \"bbb\"}, testChars={'x', 'y'})"),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testBooleans = {false, false},"
+ " testStrings = {\"aaa\", \"bbb\"}, testChars={'x', 'y'})"));
}
public void testClassArrayAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION + "Array(testClasses = {String.class, Long.class})"),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testClasses = {java.lang.String.class, java.lang.Long.class})"));
}
public void testImportedClassArrayAnnotation() {
assertGeneratedMatches(
ImmutableList.of("import javax.annotation.Nullable;"),
ImmutableList.of(TEST_ANNOTATION + "Array(testClasses = {Nullable.class, Long.class})"),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testClasses = {javax.annotation.Nullable.class, java.lang.Long.class})"));
}
public void testEnumArrayAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testEnums = {" + PROPERTY_ANNOTATION_TEST + ".TestEnum.A})"),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testEnums = {" + PROPERTY_ANNOTATION_TEST + ".TestEnum.A})"));
}
public void testArrayOfEmptyAnnotationAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testAnnotations = {@" + PROPERTY_ANNOTATION_TEST + ".OtherAnnotation})"),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testAnnotations = {@" + PROPERTY_ANNOTATION_TEST + ".OtherAnnotation})"));
}
public void testArrayOfValuedAnnotationAnnotation() {
assertGeneratedMatches(
ImmutableList.<String>of(),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testAnnotations = {@" + PROPERTY_ANNOTATION_TEST
+ ".OtherAnnotation(foo = 999)})"),
ImmutableList.of(TEST_ANNOTATION
+ "Array(testAnnotations = {@" + PROPERTY_ANNOTATION_TEST
+ ".OtherAnnotation(foo = 999)})"));
}
}