/*
* Copyright (C) 2014 RoboVM AB
*
* 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.robovm.rt.annotation;
import static org.junit.Assert.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays;
import org.junit.Test;
import org.robovm.rt.bro.annotation.Bridge;
/**
* Tests the annotation implementation classes the {@code AnnotationImplPlugin}
* compiler plugin generates.
*/
public class AnnotationTest {
public @interface Anno1 {}
@Retention(RetentionPolicy.SOURCE)
public @interface Anno2 {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Anno3 {}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Anno4 {
boolean boolean1();
boolean boolean2() default true;
byte byte1();
byte byte2() default 100;
short short1();
short short2() default 23000;
char char1();
char char2() default 46000;
int int1();
int int2() default 2_000_000_000;
long long1();
long long2() default 20_000_000_000L;
float float1();
float float2() default 1234567.654321f;
double double1();
double double2() default 7654321.234567;
String string1();
String string2() default "string2default";
Class<?> class1();
Class<?> class2() default byte.class;
Bridge anno1();
Bridge anno2() default @Bridge(symbol = "foo", dynamic = true);
boolean[] booleans1();
boolean[] booleans2() default {true, false, true};
byte[] bytes1();
byte[] bytes2() default {100, 101, 102};
short[] shorts1();
short[] shorts2() default {23000, 23001, 23002};
char[] chars1();
char[] chars2() default {46000, 46001, 46002};
int[] ints1();
int[] ints2() default {2_000_000_000, 2_000_000_001, 2_000_000_002};
long[] longs1();
long[] longs2() default {20_000_000_000L, 20_000_000_001L, 20_000_000_002L};
float[] floats1();
float[] floats2() default {1234567.654321f, 2234567.654321f, 3234567.654321f};
double[] doubles1();
double[] doubles2() default {7654321.234567, 8654321.234567, 9654321.234567};
String[] strings1();
String[] strings2() default {"a", "b", "c"};
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Anno5 {
String v1() default "v1";
String v2() default "v2";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Anno6 {
Anno1 anno1() default @Anno1;
Anno2 anno2() default @Anno2;
}
@Anno3
public static class AnnoHost1 {}
@Anno3
public static class AnnoHost2 {}
@Anno4(
boolean1 = false,
byte1 = 101,
short1 = 23001,
char1 = 46001,
int1 = 2_000_000_001,
long1 = 20_000_000_001L,
float1 = 2234567.654321f,
double1 = 8654321.234567,
string1 = "string1value",
class1 = Integer.class,
anno1 = @Bridge(symbol = "bar", dynamic = true),
booleans1 = {false, true},
bytes1 = {102, 101, 100},
shorts1 = {23002, 23001, 23000},
chars1 = {46002, 46001, 46000},
ints1 = {2_000_000_002, 2_000_000_001, 2_000_000_000},
longs1 = {20_000_000_002L, 20_000_000_001L, 20_000_000_000L},
floats1 = {3234567.654321f, 2234567.654321f, 1234567.654321f},
doubles1 = {9654321.234567, 8654321.234567, 7654321.234567},
strings1 = {"c", "b", "a"})
public static class AnnoHost3 {}
@Anno4(
boolean1 = false,
byte1 = 101,
short1 = 23001,
char1 = 46001,
int1 = 2_000_000_001,
long1 = 20_000_000_001L,
float1 = 2234567.654321f,
double1 = 8654321.234567,
string1 = "string1value",
class1 = Integer.class,
anno1 = @Bridge(symbol = "bar", dynamic = true),
booleans1 = {false, true},
bytes1 = {102, 101, 100},
shorts1 = {23002, 23001, 23000},
chars1 = {46002, 46001, 46000},
ints1 = {2_000_000_002, 2_000_000_001, 2_000_000_000},
longs1 = {20_000_000_002L, 20_000_000_001L, 20_000_000_000L},
floats1 = {3234567.654321f, 2234567.654321f, 1234567.654321f},
doubles1 = {9654321.234567, 8654321.234567, 7654321.234567},
strings1 = {"c", "b", "a"})
public static class AnnoHost4 {}
@Anno4(
boolean1 = true, // Only diff!
byte1 = 101,
short1 = 23001,
char1 = 46001,
int1 = 2_000_000_001,
long1 = 20_000_000_001L,
float1 = 2234567.654321f,
double1 = 8654321.234567,
string1 = "string1value",
class1 = Integer.class,
anno1 = @Bridge(symbol = "bar", dynamic = true),
booleans1 = {false, true},
bytes1 = {102, 101, 100},
shorts1 = {23002, 23001, 23000},
chars1 = {46002, 46001, 46000},
ints1 = {2_000_000_002, 2_000_000_001, 2_000_000_000},
longs1 = {20_000_000_002L, 20_000_000_001L, 20_000_000_000L},
floats1 = {3234567.654321f, 2234567.654321f, 1234567.654321f},
doubles1 = {9654321.234567, 8654321.234567, 7654321.234567},
strings1 = {"c", "b", "a"})
public static class AnnoHost5 {}
@Anno5
public static class AnnoHost6 {}
@Anno5
public static class AnnoHost7 {}
@Anno5(v1 = "a1", v2 = "a2")
public static class AnnoHost8 {}
@Anno5(v1 = "a1", v2 = "a2")
public static class AnnoHost9 {}
@Anno6
public static class AnnoHost10 {}
@Test
public void testIsFastImpl() {
Anno3 anno = AnnoHost1.class.getAnnotation(Anno3.class);
assertTrue(anno instanceof Annotation);
}
@Test
public void testAnnotationMethodsNoMembers() {
Anno3 anno = AnnoHost1.class.getAnnotation(Anno3.class);
assertSame(Anno3.class, anno.annotationType());
assertEquals(0, anno.hashCode());
assertTrue(anno.equals(anno));
assertEquals("@org.robovm.rt.annotation.AnnotationTest$Anno3()", anno.toString());
}
@Test
public void testSingletonAnnotation() {
Anno3 anno1 = AnnoHost1.class.getAnnotation(Anno3.class);
Anno3 anno2 = AnnoHost2.class.getAnnotation(Anno3.class);
assertSame(anno1, anno2);
}
@Test
public void testAnnotationMembersWithoutDefaults() {
Anno4 anno = AnnoHost3.class.getAnnotation(Anno4.class);
assertEquals(false, anno.boolean1());
assertEquals(101, anno.byte1());
assertEquals(23001, anno.short1());
assertEquals(46001, anno.char1());
assertEquals(2_000_000_001, anno.int1());
assertEquals(20_000_000_001L, anno.long1());
assertEquals(2234567.654321f, anno.float1(), 0.0f);
assertEquals(8654321.234567, anno.double1(), 0.0);
assertEquals("string1value", anno.string1());
assertEquals(Integer.class, anno.class1());
assertEquals("bar", anno.anno1().symbol());
assertEquals(true, anno.anno1().dynamic());
assertTrue(Arrays.equals(new boolean[] {false, true}, anno.booleans1()));
assertArrayEquals(new byte[] {102, 101, 100}, anno.bytes1());
assertArrayEquals(new short[] {23002, 23001, 23000}, anno.shorts1());
assertArrayEquals(new char[] {46002, 46001, 46000}, anno.chars1());
assertArrayEquals(new int[] {2_000_000_002, 2_000_000_001, 2_000_000_000}, anno.ints1());
assertArrayEquals(new long[] {20_000_000_002L, 20_000_000_001L, 20_000_000_000L}, anno.longs1());
assertArrayEquals(new float[] {3234567.654321f, 2234567.654321f, 1234567.654321f}, anno.floats1(), 0.0f);
assertArrayEquals(new double[] {9654321.234567, 8654321.234567, 7654321.234567}, anno.doubles1(), 0.0);
assertArrayEquals(new String[] {"c", "b", "a"}, anno.strings1());
}
@Test
public void testAnnotationMemberDefaults() {
Anno4 anno = AnnoHost3.class.getAnnotation(Anno4.class);
assertEquals(true, anno.boolean2());
assertEquals(100, anno.byte2());
assertEquals(23000, anno.short2());
assertEquals(46000, anno.char2());
assertEquals(2_000_000_000, anno.int2());
assertEquals(20_000_000_000L, anno.long2());
assertEquals(1234567.654321f, anno.float2(), 0.0f);
assertEquals(7654321.234567, anno.double2(), 0.0);
assertEquals("string2default", anno.string2());
assertEquals(byte.class, anno.class2());
assertEquals("foo", anno.anno2().symbol());
assertEquals(true, anno.anno2().dynamic());
assertTrue(Arrays.equals(new boolean[] {true, false, true}, anno.booleans2()));
assertArrayEquals(new byte[] {100, 101, 102}, anno.bytes2());
assertArrayEquals(new short[] {23000, 23001, 23002}, anno.shorts2());
assertArrayEquals(new char[] {46000, 46001, 46002}, anno.chars2());
assertArrayEquals(new int[] {2_000_000_000, 2_000_000_001, 2_000_000_002}, anno.ints2());
assertArrayEquals(new long[] {20_000_000_000L, 20_000_000_001L, 20_000_000_002L}, anno.longs2());
assertArrayEquals(new float[] {1234567.654321f, 2234567.654321f, 3234567.654321f}, anno.floats2(), 0.0f);
assertArrayEquals(new double[] {7654321.234567, 8654321.234567, 9654321.234567}, anno.doubles2(), 0.0);
assertArrayEquals(new String[] {"a", "b", "c"}, anno.strings2());
}
@Test
public void testEquals() {
Anno4 anno1 = AnnoHost3.class.getAnnotation(Anno4.class);
Anno4 anno2 = AnnoHost4.class.getAnnotation(Anno4.class);
Anno4 anno3 = AnnoHost5.class.getAnnotation(Anno4.class);
assertNotSame(anno1, anno2);
assertTrue(anno1.equals(anno2));
assertFalse(anno1.equals(anno3));
}
@Test
public void testHashCodeWithMembers() {
Anno4 anno1 = AnnoHost3.class.getAnnotation(Anno4.class);
Anno4 anno2 = AnnoHost4.class.getAnnotation(Anno4.class);
Anno4 anno3 = AnnoHost5.class.getAnnotation(Anno4.class);
assertFalse(0 == anno1.hashCode());
assertFalse(0 == anno3.hashCode());
assertEquals(anno1.hashCode(), anno2.hashCode());
assertFalse(anno1.hashCode() == anno3.hashCode());
}
@Test
public void testAccessorsReturnCopies() throws Exception {
Anno4 anno = AnnoHost3.class.getAnnotation(Anno4.class);
assertSame(anno.class1(), anno.class1());
assertSame(anno.class2(), anno.class2());
assertSame(anno.string1(), anno.string1());
assertSame(anno.string2(), anno.string2());
assertSame(anno.anno1(), anno.anno1());
assertSame(anno.anno2(), anno.anno2());
assertNotSame(anno.booleans1(), anno.booleans1());
assertNotSame(anno.booleans2(), anno.booleans2());
assertNotSame(anno.bytes1(), anno.bytes1());
assertNotSame(anno.bytes2(), anno.bytes2());
assertNotSame(anno.shorts1(), anno.shorts1());
assertNotSame(anno.shorts2(), anno.shorts2());
assertNotSame(anno.chars1(), anno.chars1());
assertNotSame(anno.chars2(), anno.chars2());
assertNotSame(anno.ints1(), anno.ints1());
assertNotSame(anno.ints2(), anno.ints2());
assertNotSame(anno.longs1(), anno.longs1());
assertNotSame(anno.longs2(), anno.longs2());
assertNotSame(anno.floats1(), anno.floats1());
assertNotSame(anno.floats2(), anno.floats2());
assertNotSame(anno.double1(), anno.double1());
assertNotSame(anno.double2(), anno.double2());
assertNotSame(anno.strings1(), anno.strings1());
assertNotSame(anno.strings2(), anno.strings2());
}
@Test
public void testSingletonWhenOnlyDefaults() throws Exception {
Anno5 anno1 = AnnoHost6.class.getAnnotation(Anno5.class);
Anno5 anno2 = AnnoHost7.class.getAnnotation(Anno5.class);
Anno5 anno3 = AnnoHost8.class.getAnnotation(Anno5.class);
Anno5 anno4 = AnnoHost9.class.getAnnotation(Anno5.class);
assertSame(anno1, anno2);
assertNotSame(anno1, anno3);
assertNotSame(anno3, anno4);
}
@Test
public void testNonRuntimeVisibleAnnotationsAsDefaultValues() throws Exception {
Anno6 anno = AnnoHost10.class.getAnnotation(Anno6.class);
assertTrue(anno.anno1() instanceof Anno1);
assertTrue(anno.anno2() instanceof Anno2);
}
}