diff options
Diffstat (limited to 'test')
40 files changed, 1506 insertions, 89 deletions
diff --git a/test/004-UnsafeTest/src/Main.java b/test/004-UnsafeTest/src/Main.java index 5b22e88014..a9a7a058e0 100644 --- a/test/004-UnsafeTest/src/Main.java +++ b/test/004-UnsafeTest/src/Main.java @@ -110,23 +110,35 @@ public class Main { check(unsafe.getObject(t, objectOffset), objectValue, "Unsafe.getObject(Object, long)"); if (unsafe.compareAndSwapInt(t, intOffset, 0, 1)) { - System.out.println("Unexpectedly succeeding compareAndSwap..."); + System.out.println("Unexpectedly succeeding compareAndSwapInt(t, intOffset, 0, 1)"); } if (!unsafe.compareAndSwapInt(t, intOffset, intValue, 0)) { - System.out.println("Unexpectedly not succeeding compareAndSwap..."); + System.out.println( + "Unexpectedly not succeeding compareAndSwapInt(t, intOffset, intValue, 0)"); } if (!unsafe.compareAndSwapInt(t, intOffset, 0, 1)) { - System.out.println("Unexpectedly not succeeding compareAndSwap..."); + System.out.println("Unexpectedly not succeeding compareAndSwapInt(t, intOffset, 0, 1)"); + } + // Exercise sun.misc.Unsafe.compareAndSwapInt using the same + // integer (1) for the `expectedValue` and `newValue` arguments. + if (!unsafe.compareAndSwapInt(t, intOffset, 1, 1)) { + System.out.println("Unexpectedly not succeeding compareAndSwapInt(t, intOffset, 1, 1)"); } if (unsafe.compareAndSwapLong(t, longOffset, 0, 1)) { - System.out.println("Unexpectedly succeeding compareAndSwapLong..."); + System.out.println("Unexpectedly succeeding compareAndSwapLong(t, longOffset, 0, 1)"); } if (!unsafe.compareAndSwapLong(t, longOffset, longValue, 0)) { - System.out.println("Unexpectedly not succeeding compareAndSwapLong..."); + System.out.println( + "Unexpectedly not succeeding compareAndSwapLong(t, longOffset, longValue, 0)"); } if (!unsafe.compareAndSwapLong(t, longOffset, 0, 1)) { - System.out.println("Unexpectedly not succeeding compareAndSwapLong..."); + System.out.println("Unexpectedly not succeeding compareAndSwapLong(t, longOffset, 0, 1)"); + } + // Exercise sun.misc.Unsafe.compareAndSwapLong using the same + // integer (1) for the `expectedValue` and `newValue` arguments. + if (!unsafe.compareAndSwapLong(t, longOffset, 1, 1)) { + System.out.println("Unexpectedly not succeeding compareAndSwapLong(t, longOffset, 1, 1)"); } // We do not use `null` as argument to sun.misc.Unsafe.compareAndSwapObject @@ -135,31 +147,41 @@ public class Main { // references). This way, when heap poisoning is enabled, we can // better exercise its implementation within that method. if (unsafe.compareAndSwapObject(t, objectOffset, new Object(), new Object())) { - System.out.println("Unexpectedly succeeding compareAndSwapObject..."); + System.out.println("Unexpectedly succeeding " + + "compareAndSwapObject(t, objectOffset, new Object(), new Object())"); } Object objectValue2 = new Object(); if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue, objectValue2)) { - System.out.println("Unexpectedly not succeeding compareAndSwapObject..."); + System.out.println("Unexpectedly not succeeding " + + "compareAndSwapObject(t, objectOffset, objectValue, objectValue2)"); } Object objectValue3 = new Object(); if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue2, objectValue3)) { - System.out.println("Unexpectedly not succeeding compareAndSwapObject..."); + System.out.println("Unexpectedly not succeeding " + + "compareAndSwapObject(t, objectOffset, objectValue2, objectValue3)"); + } + // Exercise sun.misc.Unsafe.compareAndSwapObject using the same + // object (`objectValue3`) for the `expectedValue` and `newValue` arguments. + if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue3, objectValue3)) { + System.out.println("Unexpectedly not succeeding " + + "compareAndSwapObject(t, objectOffset, objectValue3, objectValue3)"); } - // Exercise sun.misc.Unsafe.compareAndSwapObject using the same // object (`t`) for the `obj` and `newValue` arguments. if (!unsafe.compareAndSwapObject(t, objectOffset, objectValue3, t)) { - System.out.println("Unexpectedly not succeeding compareAndSwapObject..."); + System.out.println( + "Unexpectedly not succeeding compareAndSwapObject(t, objectOffset, objectValue3, t)"); } // Exercise sun.misc.Unsafe.compareAndSwapObject using the same // object (`t`) for the `obj`, `expectedValue` and `newValue` arguments. if (!unsafe.compareAndSwapObject(t, objectOffset, t, t)) { - System.out.println("Unexpectedly not succeeding compareAndSwapObject..."); + System.out.println("Unexpectedly not succeeding compareAndSwapObject(t, objectOffset, t, t)"); } // Exercise sun.misc.Unsafe.compareAndSwapObject using the same // object (`t`) for the `obj` and `expectedValue` arguments. if (!unsafe.compareAndSwapObject(t, objectOffset, t, new Object())) { - System.out.println("Unexpectedly not succeeding compareAndSwapObject..."); + System.out.println( + "Unexpectedly not succeeding compareAndSwapObject(t, objectOffset, t, new Object())"); } } diff --git a/test/048-reflect-v8/expected.txt b/test/048-reflect-v8/expected.txt index 2d0b4ccb6b..3109eccda6 100644 --- a/test/048-reflect-v8/expected.txt +++ b/test/048-reflect-v8/expected.txt @@ -1,4 +1,95 @@ -Main$DefaultInterface is default = yes -Main$RegularInterface is default = no -Main$ImplementsWithDefault is default = yes -Main$ImplementsWithRegular is default = no +============================== +Are These Methods Default: +============================== +IsDefaultTest$DefaultInterface is default = yes +IsDefaultTest$RegularInterface is default = no +IsDefaultTest$ImplementsWithDefault is default = yes +IsDefaultTest$ImplementsWithRegular is default = no +============================== +Class annotations by type: +============================== +Annotations by type, defined by class SingleUser with annotation Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) +Annotations by type, defined by class SingleUser with annotation Calendars: <empty> +Annotations by type, defined by class User with annotation Calendar: @Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23) +Annotations by type, defined by class User with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) +Annotations by type, defined by class User2 with annotation Calendar: @Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6) +Annotations by type, defined by class User2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6)]) +Annotations by type, defined by class UserComplex with annotation Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23) +Annotations by type, defined by class UserComplex with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) +Annotations by type, defined by class UserSub with annotation Calendar: @Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23) +Annotations by type, defined by class UserSub with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) +Annotations by type, defined by class UserSub2 with annotation Calendar: @Calendar(dayOfMonth=sub2, dayOfWeek=unspecified_week, hour=6) +Annotations by type, defined by class UserSub2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) +----------------------------- +----------------------------- +============================== +Class declared annotation: +============================== +Declared annotations by class class SingleUser, annotation interface Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) +Declared annotations by class class SingleUser, annotation interface Calendars: <null> +Declared annotations by class class User, annotation interface Calendar: <null> +Declared annotations by class class User, annotation interface Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) +Declared annotations by class class UserComplex, annotation interface Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6) +Declared annotations by class class UserComplex, annotation interface Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) +Declared annotations by class class UserSub, annotation interface Calendar: <null> +Declared annotations by class class UserSub, annotation interface Calendars: <null> +Declared annotations by class class UserSub2, annotation interface Calendar: @Calendar(dayOfMonth=sub2, dayOfWeek=unspecified_week, hour=6) +Declared annotations by class class UserSub2, annotation interface Calendars: <null> +----------------------------- +----------------------------- +============================== +Declared class annotations by type: +============================== +Declared annnotations by type, defined by class SingleUser with annotation Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) +Declared annnotations by type, defined by class SingleUser with annotation Calendars: <empty> +Declared annnotations by type, defined by class User with annotation Calendar: @Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23) +Declared annnotations by type, defined by class User with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) +Declared annnotations by type, defined by class User2 with annotation Calendar: @Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6) +Declared annnotations by type, defined by class User2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6)]) +Declared annnotations by type, defined by class UserComplex with annotation Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23) +Declared annnotations by type, defined by class UserComplex with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) +Declared annnotations by type, defined by class UserSub with annotation Calendar: <empty> +Declared annnotations by type, defined by class UserSub with annotation Calendars: <empty> +Declared annnotations by type, defined by class UserSub2 with annotation Calendar: @Calendar(dayOfMonth=sub2, dayOfWeek=unspecified_week, hour=6) +Declared annnotations by type, defined by class UserSub2 with annotation Calendars: <empty> +----------------------------- +----------------------------- +============================== +Method annotations by type: +============================== +Annotations by type, defined by method singleUser with annotation Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) +Annotations by type, defined by method singleUser with annotation Calendars: <empty> +Annotations by type, defined by method user with annotation Calendar: @Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23) +Annotations by type, defined by method user with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) +Annotations by type, defined by method user2 with annotation Calendar: @Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6) +Annotations by type, defined by method user2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6)]) +Annotations by type, defined by method userComplex with annotation Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23) +Annotations by type, defined by method userComplex with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) +----------------------------- +----------------------------- +============================== +Declared method annotations: +============================== +Annotations declared by method singleUser with annotation Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) +Annotations declared by method singleUser with annotation Calendars: <null> +Annotations declared by method user with annotation Calendar: <null> +Annotations declared by method user with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) +Annotations declared by method user2 with annotation Calendar: <null> +Annotations declared by method user2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6)]) +Annotations declared by method userComplex with annotation Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6) +Annotations declared by method userComplex with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) +----------------------------- +----------------------------- +============================== +Declared method annotations by type: +============================== +Annotations by type, defined by method singleUser with annotation Calendar: @Calendar(dayOfMonth=unspecified_month, dayOfWeek=single, hour=23) +Annotations by type, defined by method singleUser with annotation Calendars: <empty> +Annotations by type, defined by method user with annotation Calendar: @Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23) +Annotations by type, defined by method user with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=last, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=unspecified_month, dayOfWeek=Fri, hour=23)]) +Annotations by type, defined by method user2 with annotation Calendar: @Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6) +Annotations by type, defined by method user2 with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=z, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=x, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=y, dayOfWeek=unspecified_week, hour=6)]) +Annotations by type, defined by method userComplex with annotation Calendar: @Calendar(dayOfMonth=afirst, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23) +Annotations by type, defined by method userComplex with annotation Calendars: @Calendars(value=[@Calendar(dayOfMonth=zsecond, dayOfWeek=unspecified_week, hour=6), @Calendar(dayOfMonth=athird, dayOfWeek=unspecified_week, hour=23)]) +----------------------------- +----------------------------- diff --git a/test/048-reflect-v8/src/AnnotationTest.java b/test/048-reflect-v8/src/AnnotationTest.java new file mode 100644 index 0000000000..75e684557c --- /dev/null +++ b/test/048-reflect-v8/src/AnnotationTest.java @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +public class AnnotationTest extends AnnotationTestHelpers { + public static void testAnnotationsByType() { + System.out.println("=============================="); + System.out.println("Class annotations by type:"); + System.out.println("=============================="); + + // Print associated annotations: + // * A is directly present or repeatably present on an element E; + // * No annotation of A is directly/repeatably present on an element + // AND E is a class AND A's type is inheritable, AND A is associated with its superclass. + // (Looks through subtypes recursively only if there's 0 result at each level, + // and the annotation is @Inheritable). + printAnnotationsByType(Calendar.class, SingleUser.class); + printAnnotationsByType(Calendars.class, SingleUser.class); + + printAnnotationsByType(Calendar.class, User.class); + printAnnotationsByType(Calendars.class, User.class); + + printAnnotationsByType(Calendar.class, User2.class); // Enforce ordering 'z,x,y' + printAnnotationsByType(Calendars.class, User2.class); + + // NOTE: + // Order of outer-most annotations Calendars[C,C],S vs C,Calendars[C,C] is unspecified. + // In particular it's the order of #getDeclaredAnnotations which is completely unmentioned. + // The only requirement for #getAnnotationsByType is to have same ordering as + // #getDeclaredAnnotations. + // (Calendars[] itself has to maintain value() order). + printAnnotationsByType(Calendar.class, UserComplex.class); // Cs(C,C),C collapses into C,C,C. + printAnnotationsByType(Calendars.class, UserComplex.class); + + printAnnotationsByType(Calendar.class, UserSub.class); + printAnnotationsByType(Calendars.class, UserSub.class); + + printAnnotationsByType(Calendar.class, UserSub2.class); + // The directly present "Calendar" annotation masks all the repeatably present + // "Calendar" annotations coming from User. + printAnnotationsByType(Calendars.class, UserSub2.class); + // Edge case: UserSub2 doesn't directly have a Calendars annotation, + // so it doesn't mask the "User" Calendars annotation. + + System.out.println("-----------------------------"); + System.out.println("-----------------------------"); + + } + + public static void testDeclaredAnnotation() { + System.out.println("=============================="); + System.out.println("Class declared annotation:"); + System.out.println("=============================="); + + // Print directly present annotations: + // + // The element E has an annotation_item for it (accessible through an + // annotations_directory_item) corresponding to an annotation A, + // and A's type_idx must match that on the encoded_annotation (from the annotation_item). + // (Does not look through the subtypes recursively) + printDeclaredAnnotation(SingleUser.class, Calendar.class); + printDeclaredAnnotation(SingleUser.class, Calendars.class); + + printDeclaredAnnotation(User.class, Calendar.class); + printDeclaredAnnotation(User.class, Calendars.class); + + printDeclaredAnnotation(UserComplex.class, Calendar.class); + printDeclaredAnnotation(UserComplex.class, Calendars.class); + + printDeclaredAnnotation(UserSub.class, Calendar.class); + printDeclaredAnnotation(UserSub.class, Calendars.class); + + printDeclaredAnnotation(UserSub2.class, Calendar.class); + printDeclaredAnnotation(UserSub2.class, Calendars.class); + + System.out.println("-----------------------------"); + System.out.println("-----------------------------"); + } + + public static void testDeclaredAnnotationsByType() { + System.out.println("=============================="); + System.out.println("Declared class annotations by type:"); + System.out.println("=============================="); + + // A is directly present or repeatably present on an element E; + // -- (does not do any recursion for classes regardless of @Inherited) + printDeclaredAnnotationsByType(Calendar.class, SingleUser.class); + printDeclaredAnnotationsByType(Calendars.class, SingleUser.class); + + printDeclaredAnnotationsByType(Calendar.class, User.class); + printDeclaredAnnotationsByType(Calendars.class, User.class); + + printDeclaredAnnotationsByType(Calendar.class, User2.class); // Enforce ordering 'z,x,y' + printDeclaredAnnotationsByType(Calendars.class, User2.class); + + printDeclaredAnnotationsByType(Calendar.class, UserComplex.class); + printDeclaredAnnotationsByType(Calendars.class, UserComplex.class); + + printDeclaredAnnotationsByType(Calendar.class, UserSub.class); + printDeclaredAnnotationsByType(Calendars.class, UserSub.class); + + printDeclaredAnnotationsByType(Calendar.class, UserSub2.class); + // The directly present "Calendar" annotation masks all the repeatably present "Calendar" + // annotations coming from User. + printDeclaredAnnotationsByType(Calendars.class, UserSub2.class); + // Edge case: UserSub2 doesn't directly have a Calendars annotation, + // so it doesn't mask the "User" Calendars annotation. + + System.out.println("-----------------------------"); + System.out.println("-----------------------------"); + } + + // Print the annotation "annotationClass" that is associated with an element denoted by + // "annotationUseClass." + private static <A extends Annotation> void printAnnotationsByType(Class<A> annotationClass, + Class<?> annotationUseClass) { + A[] annotationsByType = annotationUseClass.getAnnotationsByType(annotationClass); + + String msg = "Annotations by type, defined by class " + + annotationUseClass.getName() + " with annotation " + annotationClass.getName() + ": " + + asString(annotationsByType); + + + System.out.println(msg); + } + + private static <A extends Annotation> void printDeclaredAnnotation(Class<?> annotationUseClass, + Class<A> annotationDefClass) { + A anno = annotationUseClass.getDeclaredAnnotation(annotationDefClass); + + String msg = asString(anno); + + System.out.println("Declared annotations by class " + annotationUseClass + + ", annotation " + annotationDefClass + ": " + msg); + } + + // Print the annotation "annotationClass" that is directly/indirectly present with an element + // denoted by "annotationUseClass." + private static <A extends Annotation> void printDeclaredAnnotationsByType( + Class<A> annotationClass, Class<?> annotationUseClass) { + A[] annotationsByType = annotationUseClass.getDeclaredAnnotationsByType(annotationClass); + + String msg = "Declared annnotations by type, defined by class " + annotationUseClass.getName() + + " with annotation " + annotationClass.getName() + ": " + + asString(annotationsByType); + + System.out.println(msg); + } + + public static void testMethodAnnotationsByType() { + System.out.println("=============================="); + System.out.println("Method annotations by type:"); + System.out.println("=============================="); + + // Print associated annotations: + // * A is directly present or repeatably present on an element E; + // * No annotation of A is directly/repeatably present on an element AND E is a class + // AND A's type is inheritable, AND A is associated with its superclass. + // (Looks through subtypes recursively only if there's 0 result at each level, + // and the annotation is @Inheritable). + printMethodAnnotationsByType(Calendar.class, "singleUser", AnnotationTestFixture.class); + printMethodAnnotationsByType(Calendars.class, "singleUser", AnnotationTestFixture.class); + + printMethodAnnotationsByType(Calendar.class, "user", AnnotationTestFixture.class); + printMethodAnnotationsByType(Calendars.class, "user", AnnotationTestFixture.class); + + printMethodAnnotationsByType(Calendar.class, "user2", AnnotationTestFixture.class); + printMethodAnnotationsByType(Calendars.class, "user2", AnnotationTestFixture.class); + + printMethodAnnotationsByType(Calendar.class, "userComplex", AnnotationTestFixture.class); + printMethodAnnotationsByType(Calendars.class, "userComplex", AnnotationTestFixture.class); + + System.out.println("-----------------------------"); + System.out.println("-----------------------------"); + } + + // Print the annotation "annotationClass" that is associated with an element denoted by + // "annotationUseClass" method methodName. + private static <A extends Annotation> void printMethodAnnotationsByType(Class<A> annotationClass, + String methodName, Class<?> annotationUseClass) { + Method m = null; + try { + m = annotationUseClass.getDeclaredMethod(methodName); + } catch (Throwable t) { + throw new AssertionError(t); + } + A[] annotationsByType = m.getAnnotationsByType(annotationClass); + + String msg = "Annotations by type, defined by method " + m.getName() + " with annotation " + + annotationClass.getName() + ": " + + asString(annotationsByType); + + System.out.println(msg); + } + + public static void testMethodDeclaredAnnotations() { + System.out.println("=============================="); + System.out.println("Declared method annotations:"); + System.out.println("=============================="); + + printMethodDeclaredAnnotation(Calendar.class, "singleUser", AnnotationTestFixture.class); + printMethodDeclaredAnnotation(Calendars.class, "singleUser", AnnotationTestFixture.class); + + printMethodDeclaredAnnotation(Calendar.class, "user", AnnotationTestFixture.class); + printMethodDeclaredAnnotation(Calendars.class, "user", AnnotationTestFixture.class); + + printMethodDeclaredAnnotation(Calendar.class, "user2", AnnotationTestFixture.class); + printMethodDeclaredAnnotation(Calendars.class, "user2", AnnotationTestFixture.class); + + printMethodDeclaredAnnotation(Calendar.class, "userComplex", AnnotationTestFixture.class); + printMethodDeclaredAnnotation(Calendars.class, "userComplex", AnnotationTestFixture.class); + + System.out.println("-----------------------------"); + System.out.println("-----------------------------"); + } + + // Print the annotation "annotationClass" that is associated with an element denoted by + // methodName in annotationUseClass. + private static <A extends Annotation> void printMethodDeclaredAnnotation(Class<A> annotationClass, + String methodName, Class<?> annotationUseClass) { + Method m = null; + try { + m = annotationUseClass.getDeclaredMethod(methodName); + } catch (Throwable t) { + throw new AssertionError(t); + } + Annotation annotationsByType = m.getDeclaredAnnotation(annotationClass); + + String msg = "Annotations declared by method " + m.getName() + " with annotation " + + annotationClass.getName() + ": " + + asString(annotationsByType); + + System.out.println(msg); + } + + public static void testMethodDeclaredAnnotationsByType() { + System.out.println("=============================="); + System.out.println("Declared method annotations by type:"); + System.out.println("=============================="); + + printMethodDeclaredAnnotationByType(Calendar.class, "singleUser", AnnotationTestFixture.class); + printMethodDeclaredAnnotationByType(Calendars.class, "singleUser", AnnotationTestFixture.class); + + printMethodDeclaredAnnotationByType(Calendar.class, "user", AnnotationTestFixture.class); + printMethodDeclaredAnnotationByType(Calendars.class, "user", AnnotationTestFixture.class); + + printMethodDeclaredAnnotationByType(Calendar.class, "user2", AnnotationTestFixture.class); + printMethodDeclaredAnnotationByType(Calendars.class, "user2", AnnotationTestFixture.class); + + printMethodDeclaredAnnotationByType(Calendar.class, "userComplex", AnnotationTestFixture.class); + printMethodDeclaredAnnotationByType(Calendars.class, "userComplex", + AnnotationTestFixture.class); + + System.out.println("-----------------------------"); + System.out.println("-----------------------------"); + } + + // Print the annotation "annotationClass" that is associated with an element denoted by + // methodName in annotationUseClass. + private static <A extends Annotation> void printMethodDeclaredAnnotationByType( + Class<A> annotationClass, String methodName, Class<?> annotationUseClass) { + Method m = null; + try { + m = annotationUseClass.getDeclaredMethod(methodName); + } catch (Throwable t) { + throw new AssertionError(t); + } + A[] annotationsByType = m.getDeclaredAnnotationsByType(annotationClass); + + String msg = "Annotations by type, defined by method " + m.getName() + " with annotation " + + annotationClass.getName() + ": " + + asString(annotationsByType); + + System.out.println(msg); + } +} diff --git a/test/048-reflect-v8/src/AnnotationTestFixture.java b/test/048-reflect-v8/src/AnnotationTestFixture.java new file mode 100644 index 0000000000..248dfacf3b --- /dev/null +++ b/test/048-reflect-v8/src/AnnotationTestFixture.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +public class AnnotationTestFixture { + + @Calendar(dayOfWeek="single", hour=23) + public static void singleUser() { + + } + @Calendars ({ + @Calendar(dayOfMonth="last"), + @Calendar(dayOfWeek="Fri", hour=23) + }) + public static void user() { + + } + + @Calendars ({ + @Calendar(dayOfMonth="z"), + @Calendar(dayOfMonth="x"), + @Calendar(dayOfMonth="y") + }) + public static void user2() { + + } + + @Calendar(dayOfMonth="afirst") + @Calendars ({ + @Calendar(dayOfMonth="zsecond"), + @Calendar(dayOfMonth="athird", hour=23) + }) + public static void userComplex() { + + } +} diff --git a/test/048-reflect-v8/src/AnnotationTestHelpers.java b/test/048-reflect-v8/src/AnnotationTestHelpers.java new file mode 100644 index 0000000000..6b5bea266e --- /dev/null +++ b/test/048-reflect-v8/src/AnnotationTestHelpers.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +import java.lang.annotation.Annotation; + +public class AnnotationTestHelpers { + // Provide custom print function that print a deterministic output. + // Note that Annotation#toString has unspecified order: it prints out the + // fields, which is why we can't rely on it. + + public static String asString(Annotation anno) { + if (anno instanceof Calendar) { + return asString((Calendar)anno); + } else if (anno instanceof Calendars) { + return asString((Calendars)anno); + } else { + if (anno == null) { + return "<null>"; + } + // Fall-back, usually would only go here in a test failure. + return anno.toString(); + } + } + + public static String asString(Annotation[] annos) { + String msg = ""; + + if (annos == null) { + msg += "<null>"; + } else if (annos.length == 0) { + msg += "<empty>"; + } else { + for (int i = 0; i < annos.length; ++i) { + msg += asString(annos[i]); + + if (i != annos.length - 1) { + msg += ", "; + } + } + } + + return msg; + } + + public static String asString(Calendar calendar) { + if (calendar == null) { + return "<null>"; + } + + return "@Calendar(dayOfMonth=" + calendar.dayOfMonth() + ", dayOfWeek=" + + calendar.dayOfWeek() + ", hour=" + calendar.hour() + ")"; + } + + public static String asString(Calendars calendars) { + if (calendars == null) { + return "<null>"; + } + + String s = "@Calendars(value=["; + + Calendar[] allValues = calendars.value(); + for (int i = 0; i < allValues.length; ++i) { + s += asString(allValues[i]); + if (i != allValues.length - 1) { + s += ", "; + } + } + + s += "])"; + + return s; + } +} diff --git a/test/048-reflect-v8/src/Calendar.java b/test/048-reflect-v8/src/Calendar.java new file mode 100644 index 0000000000..4a16573bca --- /dev/null +++ b/test/048-reflect-v8/src/Calendar.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +import java.lang.annotation.Inherited; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +// This is a plain old non-1.8 annotation. At runtime we can see that it has a +// "Repeatable" annotation if we query with getDeclaredAnnotation(Repeatable.class) +@Retention(RetentionPolicy.RUNTIME) +@Repeatable(Calendars.class) +@Inherited // note: container must also be @Inherited by JLS. +public @interface Calendar { + String dayOfMonth() default "unspecified_month"; + String dayOfWeek() default "unspecified_week"; + int hour() default 6; +} + diff --git a/test/048-reflect-v8/src/Calendars.java b/test/048-reflect-v8/src/Calendars.java new file mode 100644 index 0000000000..caeda52ea6 --- /dev/null +++ b/test/048-reflect-v8/src/Calendars.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +// Plain old annotation, there's nothing 1.8 specific about it. +@Retention(RetentionPolicy.RUNTIME) +@Inherited // note: elements must also be @Inherited by JLS. +public @interface Calendars { + Calendar[] value(); +} diff --git a/test/048-reflect-v8/src/IFaceA.java b/test/048-reflect-v8/src/IFaceA.java new file mode 100644 index 0000000000..9b1f610f84 --- /dev/null +++ b/test/048-reflect-v8/src/IFaceA.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +// Stored as a complex annotation Calendars(Calendar,Calendar) +// in the binary. +@Calendars ({ + @Calendar(dayOfMonth="if_a_first"), + @Calendar(dayOfMonth="if_b_last") +}) +public interface IFaceA { +} diff --git a/test/048-reflect-v8/src/IFaceSimple.java b/test/048-reflect-v8/src/IFaceSimple.java new file mode 100644 index 0000000000..93cf61057e --- /dev/null +++ b/test/048-reflect-v8/src/IFaceSimple.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +// Simple annotation, no container. +@Calendar(dayOfMonth="if_simple_first") +public interface IFaceSimple { + +} diff --git a/test/048-reflect-v8/src/IsDefaultTest.java b/test/048-reflect-v8/src/IsDefaultTest.java new file mode 100644 index 0000000000..177dcf1ab9 --- /dev/null +++ b/test/048-reflect-v8/src/IsDefaultTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +import java.lang.reflect.Method; + +public class IsDefaultTest { + interface DefaultInterface { + default void sayHi() { + System.out.println("hi default"); + } + } + + interface RegularInterface { + void sayHi(); + } + + class ImplementsWithDefault implements DefaultInterface {} + class ImplementsWithRegular implements RegularInterface { + public void sayHi() { + System.out.println("hello specific"); + } + } + + private static void printIsDefault(Class<?> klass) { + Method m; + try { + m = klass.getMethod("sayHi"); + } catch (Throwable t) { + System.out.println(t); + return; + } + + boolean isDefault = m.isDefault(); + System.out.println(klass.getName() + " is default = " + (isDefault ? "yes" : "no")); + } + + public static void test() { + System.out.println("=============================="); + System.out.println("Are These Methods Default:"); + System.out.println("=============================="); + + printIsDefault(DefaultInterface.class); + printIsDefault(RegularInterface.class); + printIsDefault(ImplementsWithDefault.class); + printIsDefault(ImplementsWithRegular.class); + } +} diff --git a/test/048-reflect-v8/src/Main.java b/test/048-reflect-v8/src/Main.java index 7fa2a923d7..f2b8287d18 100644 --- a/test/048-reflect-v8/src/Main.java +++ b/test/048-reflect-v8/src/Main.java @@ -14,43 +14,14 @@ * limitations under the License. */ -import java.lang.reflect.Method; - public class Main { - interface DefaultInterface { - default void sayHi() { - System.out.println("hi default"); - } - } - - interface RegularInterface { - void sayHi(); - } - - class ImplementsWithDefault implements DefaultInterface {} - class ImplementsWithRegular implements RegularInterface { - public void sayHi() { - System.out.println("hello specific"); - } - } - - private static void printIsDefault(Class<?> klass) { - Method m; - try { - m = klass.getMethod("sayHi"); - } catch (Throwable t) { - System.out.println(t); - return; - } - - boolean isDefault = m.isDefault(); - System.out.println(klass.getName() + " is default = " + (isDefault ? "yes" : "no")); - } - public static void main(String[] args) { - printIsDefault(DefaultInterface.class); - printIsDefault(RegularInterface.class); - printIsDefault(ImplementsWithDefault.class); - printIsDefault(ImplementsWithRegular.class); + IsDefaultTest.test(); + AnnotationTest.testAnnotationsByType(); + AnnotationTest.testDeclaredAnnotation(); + AnnotationTest.testDeclaredAnnotationsByType(); + AnnotationTest.testMethodAnnotationsByType(); + AnnotationTest.testMethodDeclaredAnnotations(); + AnnotationTest.testMethodDeclaredAnnotationsByType(); } } diff --git a/test/048-reflect-v8/src/SingleUser.java b/test/048-reflect-v8/src/SingleUser.java new file mode 100644 index 0000000000..0f9c430109 --- /dev/null +++ b/test/048-reflect-v8/src/SingleUser.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +// Stored as a single "Calendar" annotation in the binary. +@Calendar(dayOfWeek="single", hour=23) +public class SingleUser { + +} diff --git a/test/048-reflect-v8/src/User.java b/test/048-reflect-v8/src/User.java new file mode 100644 index 0000000000..003ceeb093 --- /dev/null +++ b/test/048-reflect-v8/src/User.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +// Stored as a complex annotation Calendars(Calendar,Calendar) +// in the binary. +// +/* FIXME: Use this code instead, when Jack supports repeatable annotations properly. + * + * @Calendar(dayOfMonth="last") + * @Calendar(dayOfWeek="Fri", hour=23) + */ +@Calendars ({ + @Calendar(dayOfMonth="last"), + @Calendar(dayOfWeek="Fri", hour=23) +}) +public class User { + +} diff --git a/test/048-reflect-v8/src/User2.java b/test/048-reflect-v8/src/User2.java new file mode 100644 index 0000000000..1a6049f508 --- /dev/null +++ b/test/048-reflect-v8/src/User2.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +// Stored as a complex annotation Calendars(Calendar,Calendar,Calendar) +// in the binary. +// (Check for order, should be z,x,y) +@Calendars ({ + @Calendar(dayOfMonth="z"), + @Calendar(dayOfMonth="x"), + @Calendar(dayOfMonth="y") +}) +public class User2 { + +} diff --git a/test/048-reflect-v8/src/UserComplex.java b/test/048-reflect-v8/src/UserComplex.java new file mode 100644 index 0000000000..e26234960b --- /dev/null +++ b/test/048-reflect-v8/src/UserComplex.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +// Stored as a complex annotation Calendars(Calendar,Calendar) +// followed by a Calendar in the binary. +// In other words { Calendars([C,C]), C } +// +// Note that trying to do {C,Calendars,C} or similar +// is illegal by the JLS. +@Calendar(dayOfMonth="afirst") +@Calendars ({ + @Calendar(dayOfMonth="zsecond"), + @Calendar(dayOfMonth="athird", hour=23) +}) +// @Calendar(dayOfMonth="zlast") // Leave for future ordering test +public class UserComplex { + +} diff --git a/test/048-reflect-v8/src/UserSub.java b/test/048-reflect-v8/src/UserSub.java new file mode 100644 index 0000000000..d60aa6a3f1 --- /dev/null +++ b/test/048-reflect-v8/src/UserSub.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +public class UserSub + extends User + implements IFaceA, IFaceSimple { + +} diff --git a/test/048-reflect-v8/src/UserSub2.java b/test/048-reflect-v8/src/UserSub2.java new file mode 100644 index 0000000000..13e2eb07c8 --- /dev/null +++ b/test/048-reflect-v8/src/UserSub2.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +// This calendar subsumes anything else we would've normally gotten from the subclass. +@Calendar(dayOfMonth="sub2") +public class UserSub2 + extends User + implements IFaceA, IFaceSimple { + +} diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc index 77301d20e8..87656bcf0e 100644 --- a/test/137-cfi/cfi.cc +++ b/test/137-cfi/cfi.cc @@ -101,7 +101,12 @@ static bool IsPicImage() { } #endif -extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindInProcess(JNIEnv*, jobject, jint, jboolean) { +extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindInProcess( + JNIEnv*, + jobject, + jboolean full_signatrues, + jint, + jboolean) { #if __linux__ if (IsPicImage()) { LOG(INFO) << "Image is pic, in-process unwinding check bypassed."; @@ -122,14 +127,21 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindInProcess(JNIEnv*, jobject // We cannot really parse an exact stack, as the optimizing compiler may inline some functions. // This is also risky, as deduping might play a trick on us, so the test needs to make sure that // only unique functions are being expected. + // "mini-debug-info" does not include parameters to save space. std::vector<std::string> seq = { "Java_Main_unwindInProcess", // This function. - "boolean Main.unwindInProcess(int, boolean)", // The corresponding Java native method frame. + "Main.unwindInProcess", // The corresponding Java native method frame. + "int java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)", // Framework method. + "Main.main" // The Java entry method. + }; + std::vector<std::string> full_seq = { + "Java_Main_unwindInProcess", // This function. + "boolean Main.unwindInProcess(boolean, int, boolean)", // The corresponding Java native method frame. "int java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)", // Framework method. "void Main.main(java.lang.String[])" // The Java entry method. }; - bool result = CheckStack(bt.get(), seq); + bool result = CheckStack(bt.get(), full_signatrues ? full_seq : seq); if (!kCauseSegfault) { return result ? JNI_TRUE : JNI_FALSE; } else { @@ -178,7 +190,11 @@ int wait_for_sigstop(pid_t tid, int* total_sleep_time_usec, bool* detach_failed } #endif -extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindOtherProcess(JNIEnv*, jobject, jint pid_int) { +extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindOtherProcess( + JNIEnv*, + jobject, + jboolean full_signatrues, + jint pid_int) { #if __linux__ // TODO: What to do on Valgrind? pid_t pid = static_cast<pid_t>(pid_int); @@ -214,17 +230,27 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindOtherProcess(JNIEnv*, jobj if (result) { // See comment in unwindInProcess for non-exact stack matching. + // "mini-debug-info" does not include parameters to save space. std::vector<std::string> seq = { // "Java_Main_sleep", // The sleep function being executed in the // other runtime. // Note: For some reason, the name isn't // resolved, so don't look for it right now. + "Main.sleep", // The corresponding Java native method frame. + "int java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)", // Framework method. + "Main.main" // The Java entry method. + }; + std::vector<std::string> full_seq = { + // "Java_Main_sleep", // The sleep function being executed in the + // other runtime. + // Note: For some reason, the name isn't + // resolved, so don't look for it right now. "boolean Main.sleep(int, boolean, double)", // The corresponding Java native method frame. "int java.util.Arrays.binarySearch(java.lang.Object[], int, int, java.lang.Object, java.util.Comparator)", // Framework method. "void Main.main(java.lang.String[])" // The Java entry method. }; - result = CheckStack(bt.get(), seq); + result = CheckStack(bt.get(), full_signatrues ? full_seq : seq); } if (ptrace(PTRACE_DETACH, pid, 0, 0) != 0) { diff --git a/test/137-cfi/expected.txt b/test/137-cfi/expected.txt index 6a5618ebc6..8db7853696 100644 --- a/test/137-cfi/expected.txt +++ b/test/137-cfi/expected.txt @@ -1 +1,2 @@ JNI_OnLoad called +JNI_OnLoad called diff --git a/test/137-cfi/run b/test/137-cfi/run index 9c567b6813..6f4bcfe658 100755 --- a/test/137-cfi/run +++ b/test/137-cfi/run @@ -14,4 +14,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -exec ${RUN} "$@" -Xcompiler-option --generate-debug-info +# Test with full DWARF debugging information. +# Check full signatures of methods. +${RUN} "$@" -Xcompiler-option --generate-debug-info --args --full-signatures + +# Test with minimal compressed debugging information. +# Check only method names (parameters are omitted to save space). +${RUN} "$@" -Xcompiler-option --generate-mini-debug-info diff --git a/test/137-cfi/src/Main.java b/test/137-cfi/src/Main.java index 5474c9b7b6..77553380c8 100644 --- a/test/137-cfi/src/Main.java +++ b/test/137-cfi/src/Main.java @@ -34,19 +34,28 @@ public class Main implements Comparator<Main> { private boolean secondary; + private boolean full_signatures; + private boolean passed; - public Main(boolean secondary) { + public Main(boolean secondary, boolean full_signatures) { this.secondary = secondary; + this.full_signatures = full_signatures; } public static void main(String[] args) throws Exception { System.loadLibrary(args[0]); boolean secondary = false; - if (args.length > 0 && args[args.length - 1].equals("--secondary")) { + boolean full_signatures = false; + for (String arg : args) { + if (arg.equals("--secondary")) { secondary = true; + } + if (arg.equals("--full-signatures")) { + full_signatures = true; + } } - new Main(secondary).run(); + new Main(secondary, full_signatures).run(); } private void run() { @@ -96,7 +105,7 @@ public class Main implements Comparator<Main> { throw new RuntimeException(e); } - if (!unwindOtherProcess(pid)) { + if (!unwindOtherProcess(full_signatures, pid)) { System.out.println("Unwinding other process failed."); } } finally { @@ -154,7 +163,7 @@ public class Main implements Comparator<Main> { if (b) { return sleep(2, b, 1.0); } else { - return unwindInProcess(1, b); + return unwindInProcess(full_signatures, 1, b); } } @@ -162,6 +171,6 @@ public class Main implements Comparator<Main> { public native boolean sleep(int i, boolean b, double dummy); - public native boolean unwindInProcess(int i, boolean b); - public native boolean unwindOtherProcess(int pid); + public native boolean unwindInProcess(boolean full_signatures, int i, boolean b); + public native boolean unwindOtherProcess(boolean full_signatures, int pid); } diff --git a/test/564-checker-bitcount/src/Main.java b/test/564-checker-bitcount/src/Main.java index b250145ef3..2683b2548f 100644 --- a/test/564-checker-bitcount/src/Main.java +++ b/test/564-checker-bitcount/src/Main.java @@ -16,24 +16,20 @@ public class Main { - // TODO: make this work when b/26700769 is done. - // + // TODO: make something like this work when b/26700769 is done. // CHECK-START-X86_64: int Main.bits32(int) disassembly (after) // CHECK-DAG: popcnt - // - // CHECK-START-X86_64: int Main.bits32(int) disassembly (after) - // CHECK-NOT: call + + /// CHECK-START: int Main.bits32(int) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerBitCount + /// CHECK-DAG: Return [<<Result>>] private static int bits32(int x) { return Integer.bitCount(x); } - // TODO: make this work when b/26700769 is done. - // - // CHECK-START-X86_64: int Main.bits64(long) disassembly (after) - // CHECK-DAG: popcnt - // - // CHECK-START-X86_64: int Main.bits64(long) disassembly (after) - // CHECK-NOT: call + /// CHECK-START: int Main.bits64(long) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongBitCount + /// CHECK-DAG: Return [<<Result>>] private static int bits64(long x) { return Long.bitCount(x); } diff --git a/test/565-checker-irreducible-loop/expected.txt b/test/565-checker-irreducible-loop/expected.txt new file mode 100644 index 0000000000..6ed281c757 --- /dev/null +++ b/test/565-checker-irreducible-loop/expected.txt @@ -0,0 +1,2 @@ +1 +1 diff --git a/test/565-checker-irreducible-loop/info.txt b/test/565-checker-irreducible-loop/info.txt new file mode 100644 index 0000000000..1e0dd02284 --- /dev/null +++ b/test/565-checker-irreducible-loop/info.txt @@ -0,0 +1,2 @@ +Regression test for optimizing in the presence of +an irreducible loop. diff --git a/test/565-checker-irreducible-loop/smali/IrreducibleLoop.smali b/test/565-checker-irreducible-loop/smali/IrreducibleLoop.smali new file mode 100644 index 0000000000..29547ca85e --- /dev/null +++ b/test/565-checker-irreducible-loop/smali/IrreducibleLoop.smali @@ -0,0 +1,101 @@ +# Copyright (C) 2016 The Android Open Source Project +# +# 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. + +.class public LIrreducibleLoop; + +.super Ljava/lang/Object; + +# Check that both the irreducible loop and the other loop entry +# move the constant-folded value to where it's expected. + +## CHECK-START-X86: int IrreducibleLoop.test1(int, long) register (after) +## CHECK-DAG: ParallelMove {{.*84->.*}} loop:none +## CHECK-DAG: ParallelMove {{.*84->.*}} loop:{{B\d+}} irreducible:true +.method public static test1(IJ)I + .registers 10 + const/16 v6, 2 + const/16 v4, 1 + const-wide/16 v0, 42 + add-long v2, v0, v0 + + if-eqz p0, :loop_entry + goto :other_loop_pre_entry + + # The then part: beginning of the irreducible loop. + :loop_entry + if-eqz p0, :exit + cmp-long v6, v2, p1 + :other_loop_entry + sub-int p0, p0, v4 + goto :loop_entry + + # The other block branching to the irreducible loop. + # In that block, v4 has no live range. + :other_loop_pre_entry + goto :other_loop_entry + + :exit + return v6 +.end method + +# Check that the compiler does not crash when +# a live interval is found while connecting siblings, but that +# live interval is inactive at the desired position. + +## CHECK-START-X86: int IrreducibleLoop.test2(int, long) register (after) +## CHECK-DAG: ParallelMove {{.*84->.*}} loop:none +## CHECK-DAG: ParallelMove {{.*84->.*}} loop:{{B\d+}} irreducible:true +.method public static test2(IJ)I + .registers 14 + const/16 v6, 2 + const/16 v4, 1 + const-wide/16 v0, 42 + const-wide/16 v8, 68 + add-long v2, v0, v0 + + if-eqz p0, :loop_entry + goto :other_loop_pre_entry + + # The then part: beginning of the irreducible loop. + :loop_entry + if-eqz p0, :exit + cmp-long v6, v2, p1 + :other_loop_entry + sub-int p0, p0, v4 + goto :loop_entry + + # The other block branching to the irreducible loop. + :other_loop_pre_entry + # Make v2 have a register location. + sput-wide v2, LIrreducibleLoop;->myField:J + # Stress register allocator on x86 to split v2. + sput-wide v0, LIrreducibleLoop;->myField:J + sput-wide p1, LIrreducibleLoop;->myField:J + sput-wide v8, LIrreducibleLoop;->myField:J + if-eqz p0, :join + # Stress register allocator on x86 to split v2. + sput-wide p1, LIrreducibleLoop;->myField:J + sput-wide v8, LIrreducibleLoop;->myField:J + sput-wide v0, LIrreducibleLoop;->myField:J + # Last use of v2 before the irreducible loop, that + # will create an interval hole. + sput-wide v2, LIrreducibleLoop;->myField:J + :join + goto :other_loop_entry + + :exit + return v6 +.end method + +.field public static volatile myField:J diff --git a/test/565-checker-irreducible-loop/src/Main.java b/test/565-checker-irreducible-loop/src/Main.java new file mode 100644 index 0000000000..e48bd6b411 --- /dev/null +++ b/test/565-checker-irreducible-loop/src/Main.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +import java.lang.reflect.Method; + +public class Main { + // Workaround for b/18051191. + class InnerClass {} + + public static void main(String[] args) throws Exception { + Class<?> c = Class.forName("IrreducibleLoop"); + { + Method m = c.getMethod("test1", int.class, long.class); + Object[] arguments = { 42, 31L }; + System.out.println(m.invoke(null, arguments)); + } + + { + Method m = c.getMethod("test2", int.class, long.class); + Object[] arguments = { 42, 31L }; + System.out.println(m.invoke(null, arguments)); + } + } +} diff --git a/test/565-checker-rotate/expected.txt b/test/565-checker-rotate/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/565-checker-rotate/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/565-checker-rotate/info.txt b/test/565-checker-rotate/info.txt new file mode 100644 index 0000000000..c6a8091d6c --- /dev/null +++ b/test/565-checker-rotate/info.txt @@ -0,0 +1 @@ +Unit test for 32-bit and 64-bit rotate operations. diff --git a/test/565-checker-rotate/src/Main.java b/test/565-checker-rotate/src/Main.java new file mode 100644 index 0000000000..33bbe0255a --- /dev/null +++ b/test/565-checker-rotate/src/Main.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +public class Main { + + /// CHECK-START: int Main.rotateLeft32(int, int) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerRotateLeft + /// CHECK-DAG: Return [<<Result>>] + private static int rotateLeft32(int x, int y) { + return Integer.rotateLeft(x, y); + } + + /// CHECK-START: long Main.rotateLeft64(long, int) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect intrinsic:LongRotateLeft + /// CHECK-DAG: Return [<<Result>>] + private static long rotateLeft64(long x, int y) { + return Long.rotateLeft(x, y); + } + + /// CHECK-START: int Main.rotateRight32(int, int) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerRotateRight + /// CHECK-DAG: Return [<<Result>>] + private static int rotateRight32(int x, int y) { + return Integer.rotateRight(x, y); + } + + /// CHECK-START: long Main.rotateRight64(long, int) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect intrinsic:LongRotateRight + /// CHECK-DAG: Return [<<Result>>] + private static long rotateRight64(long x, int y) { + return Long.rotateRight(x, y); + } + + public static void main(String args[]) { + expectEquals32(0x00000001, rotateLeft32(0x00000001, 0)); + expectEquals32(0x00000002, rotateLeft32(0x00000001, 1)); + expectEquals32(0x80000000, rotateLeft32(0x00000001, 31)); + expectEquals32(0x00000001, rotateLeft32(0x00000001, 32)); // overshoot + expectEquals32(0x00000003, rotateLeft32(0x80000001, 1)); + expectEquals32(0x00000006, rotateLeft32(0x80000001, 2)); + expectEquals32(0x23456781, rotateLeft32(0x12345678, 4)); + expectEquals32(0xBCDEF09A, rotateLeft32(0x9ABCDEF0, 8)); + for (int i = 0; i < 40; i++) { // overshoot a bit + int j = i & 31; + expectEquals32(0x00000000, rotateLeft32(0x00000000, i)); + expectEquals32(0xFFFFFFFF, rotateLeft32(0xFFFFFFFF, i)); + expectEquals32(1 << j, rotateLeft32(0x00000001, i)); + expectEquals32((0x12345678 << j) | (0x12345678 >>> -j), + rotateLeft32(0x12345678, i)); + } + + expectEquals64(0x0000000000000001L, rotateLeft64(0x0000000000000001L, 0)); + expectEquals64(0x0000000000000002L, rotateLeft64(0x0000000000000001L, 1)); + expectEquals64(0x8000000000000000L, rotateLeft64(0x0000000000000001L, 63)); + expectEquals64(0x0000000000000001L, rotateLeft64(0x0000000000000001L, 64)); // overshoot + expectEquals64(0x0000000000000003L, rotateLeft64(0x8000000000000001L, 1)); + expectEquals64(0x0000000000000006L, rotateLeft64(0x8000000000000001L, 2)); + expectEquals64(0x23456789ABCDEF01L, rotateLeft64(0x123456789ABCDEF0L, 4)); + expectEquals64(0x3456789ABCDEF012L, rotateLeft64(0x123456789ABCDEF0L, 8)); + for (int i = 0; i < 70; i++) { // overshoot a bit + int j = i & 63; + expectEquals64(0x0000000000000000L, rotateLeft64(0x0000000000000000L, i)); + expectEquals64(0xFFFFFFFFFFFFFFFFL, rotateLeft64(0xFFFFFFFFFFFFFFFFL, i)); + expectEquals64(1L << j, rotateLeft64(0x0000000000000001, i)); + expectEquals64((0x123456789ABCDEF0L << j) | (0x123456789ABCDEF0L >>> -j), + rotateLeft64(0x123456789ABCDEF0L, i)); + } + + expectEquals32(0x80000000, rotateRight32(0x80000000, 0)); + expectEquals32(0x40000000, rotateRight32(0x80000000, 1)); + expectEquals32(0x00000001, rotateRight32(0x80000000, 31)); + expectEquals32(0x80000000, rotateRight32(0x80000000, 32)); // overshoot + expectEquals32(0xC0000000, rotateRight32(0x80000001, 1)); + expectEquals32(0x60000000, rotateRight32(0x80000001, 2)); + expectEquals32(0x81234567, rotateRight32(0x12345678, 4)); + expectEquals32(0xF09ABCDE, rotateRight32(0x9ABCDEF0, 8)); + for (int i = 0; i < 40; i++) { // overshoot a bit + int j = i & 31; + expectEquals32(0x00000000, rotateRight32(0x00000000, i)); + expectEquals32(0xFFFFFFFF, rotateRight32(0xFFFFFFFF, i)); + expectEquals32(0x80000000 >>> j, rotateRight32(0x80000000, i)); + expectEquals32((0x12345678 >>> j) | (0x12345678 << -j), + rotateRight32(0x12345678, i)); + } + + expectEquals64(0x8000000000000000L, rotateRight64(0x8000000000000000L, 0)); + expectEquals64(0x4000000000000000L, rotateRight64(0x8000000000000000L, 1)); + expectEquals64(0x0000000000000001L, rotateRight64(0x8000000000000000L, 63)); + expectEquals64(0x8000000000000000L, rotateRight64(0x8000000000000000L, 64)); // overshoot + expectEquals64(0xC000000000000000L, rotateRight64(0x8000000000000001L, 1)); + expectEquals64(0x6000000000000000L, rotateRight64(0x8000000000000001L, 2)); + expectEquals64(0x0123456789ABCDEFL, rotateRight64(0x123456789ABCDEF0L, 4)); + expectEquals64(0xF0123456789ABCDEL, rotateRight64(0x123456789ABCDEF0L, 8)); + for (int i = 0; i < 70; i++) { // overshoot a bit + int j = i & 63; + expectEquals64(0x0000000000000000L, rotateRight64(0x0000000000000000L, i)); + expectEquals64(0xFFFFFFFFFFFFFFFFL, rotateRight64(0xFFFFFFFFFFFFFFFFL, i)); + expectEquals64(0x8000000000000000L >>> j, rotateRight64(0x8000000000000000L, i)); + expectEquals64((0x123456789ABCDEF0L >>> j) | (0x123456789ABCDEF0L << -j), + rotateRight64(0x123456789ABCDEF0L, i)); + } + + System.out.println("passed"); + } + + private static void expectEquals32(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + private static void expectEquals64(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/566-checker-signum/expected.txt b/test/566-checker-signum/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/566-checker-signum/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/566-checker-signum/info.txt b/test/566-checker-signum/info.txt new file mode 100644 index 0000000000..328e494291 --- /dev/null +++ b/test/566-checker-signum/info.txt @@ -0,0 +1 @@ +Unit test for 32-bit and 64-bit signum operations. diff --git a/test/566-checker-signum/src/Main.java b/test/566-checker-signum/src/Main.java new file mode 100644 index 0000000000..cc4a98469c --- /dev/null +++ b/test/566-checker-signum/src/Main.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +public class Main { + + /// CHECK-START: int Main.sign32(int) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerSignum + /// CHECK-DAG: Return [<<Result>>] + private static int sign32(int x) { + return Integer.signum(x); + } + + /// CHECK-START: int Main.sign64(long) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongSignum + /// CHECK-DAG: Return [<<Result>>] + private static int sign64(long x) { + return Long.signum(x); + } + + public static void main(String args[]) { + expectEquals(-1, sign32(Integer.MIN_VALUE)); + expectEquals(-1, sign32(-12345)); + expectEquals(-1, sign32(-1)); + expectEquals(0, sign32(0)); + expectEquals(1, sign32(1)); + expectEquals(1, sign32(12345)); + expectEquals(1, sign32(Integer.MAX_VALUE)); + + for (int i = -11; i <= 11; i++) { + int expected = 0; + if (i < 0) expected = -1; + else if (i > 0) expected = 1; + expectEquals(expected, sign32(i)); + } + + expectEquals(-1, sign64(Long.MIN_VALUE)); + expectEquals(-1, sign64(-12345L)); + expectEquals(-1, sign64(-1L)); + expectEquals(0, sign64(0L)); + expectEquals(1, sign64(1L)); + expectEquals(1, sign64(12345L)); + expectEquals(1, sign64(Long.MAX_VALUE)); + + for (long i = -11L; i <= 11L; i++) { + int expected = 0; + if (i < 0) expected = -1; + else if (i > 0) expected = 1; + expectEquals(expected, sign64(i)); + } + + System.out.println("passed"); + } + + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/567-checker-compare/expected.txt b/test/567-checker-compare/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/567-checker-compare/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/567-checker-compare/info.txt b/test/567-checker-compare/info.txt new file mode 100644 index 0000000000..5bac7b1165 --- /dev/null +++ b/test/567-checker-compare/info.txt @@ -0,0 +1 @@ +Unit test for 32-bit and 64-bit compare operations. diff --git a/test/567-checker-compare/src/Main.java b/test/567-checker-compare/src/Main.java new file mode 100644 index 0000000000..52abb75e89 --- /dev/null +++ b/test/567-checker-compare/src/Main.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +public class Main { + + /// CHECK-START: int Main.compare32(int, int) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerCompare + /// CHECK-DAG: Return [<<Result>>] + private static int compare32(int x, int y) { + return Integer.compare(x, y); + } + + /// CHECK-START: int Main.compare64(long, long) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongCompare + /// CHECK-DAG: Return [<<Result>>] + private static int compare64(long x, long y) { + return Long.compare(x, y); + } + + public static void main(String args[]) { + expectEquals(-1, compare32(Integer.MIN_VALUE, Integer.MIN_VALUE + 1)); + expectEquals(-1, compare32(Integer.MIN_VALUE, -1)); + expectEquals(-1, compare32(Integer.MIN_VALUE, 0)); + expectEquals(-1, compare32(Integer.MIN_VALUE, 1)); + expectEquals(-1, compare32(Integer.MIN_VALUE, Integer.MAX_VALUE)); + expectEquals(-1, compare32(-1, 0)); + expectEquals(-1, compare32(-1, 1)); + expectEquals(-1, compare32(0, 1)); + + expectEquals(0, compare32(Integer.MIN_VALUE, Integer.MIN_VALUE)); + expectEquals(0, compare32(-1, -1)); + expectEquals(0, compare32(0, 0)); + expectEquals(0, compare32(1, 1)); + expectEquals(0, compare32(Integer.MAX_VALUE, Integer.MAX_VALUE)); + + expectEquals(1, compare32(0, -1)); + expectEquals(1, compare32(1, -1)); + expectEquals(1, compare32(1, 0)); + expectEquals(1, compare32(Integer.MAX_VALUE, Integer.MIN_VALUE)); + expectEquals(1, compare32(Integer.MAX_VALUE, -1)); + expectEquals(1, compare32(Integer.MAX_VALUE, 0)); + expectEquals(1, compare32(Integer.MAX_VALUE, 1)); + expectEquals(1, compare32(Integer.MAX_VALUE, Integer.MAX_VALUE - 1)); + + for (int i = -11; i <= 11; i++) { + for (int j = -11; j <= 11; j++) { + int expected = 0; + if (i < j) expected = -1; + else if (i > j) expected = 1; + expectEquals(expected, compare32(i, j)); + } + } + + expectEquals(-1, compare64(Long.MIN_VALUE, Long.MIN_VALUE + 1L)); + expectEquals(-1, compare64(Long.MIN_VALUE, -1L)); + expectEquals(-1, compare64(Long.MIN_VALUE, 0L)); + expectEquals(-1, compare64(Long.MIN_VALUE, 1L)); + expectEquals(-1, compare64(Long.MIN_VALUE, Long.MAX_VALUE)); + expectEquals(-1, compare64(-1L, 0L)); + expectEquals(-1, compare64(-1L, 1L)); + expectEquals(-1, compare64(0L, 1L)); + + expectEquals(0, compare64(Long.MIN_VALUE, Long.MIN_VALUE)); + expectEquals(0, compare64(-1L, -1L)); + expectEquals(0, compare64(0L, 0L)); + expectEquals(0, compare64(1L, 1L)); + expectEquals(0, compare64(Long.MAX_VALUE, Long.MAX_VALUE)); + + expectEquals(1, compare64(0L, -1L)); + expectEquals(1, compare64(1L, -1L)); + expectEquals(1, compare64(1L, 0L)); + expectEquals(1, compare64(Long.MAX_VALUE, Long.MIN_VALUE)); + expectEquals(1, compare64(Long.MAX_VALUE, -1L)); + expectEquals(1, compare64(Long.MAX_VALUE, 0L)); + expectEquals(1, compare64(Long.MAX_VALUE, 1L)); + expectEquals(1, compare64(Long.MAX_VALUE, Long.MAX_VALUE - 1L)); + + for (long i = -11L; i <= 11L; i++) { + for (long j = -11L; j <= 11L; j++) { + int expected = 0; + if (i < j) expected = -1; + else if (i > j) expected = 1; + expectEquals(expected, compare64(i, j)); + } + } + + System.out.println("passed"); + } + + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/568-checker-onebit/expected.txt b/test/568-checker-onebit/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/568-checker-onebit/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/568-checker-onebit/info.txt b/test/568-checker-onebit/info.txt new file mode 100644 index 0000000000..c2b5bf8688 --- /dev/null +++ b/test/568-checker-onebit/info.txt @@ -0,0 +1 @@ +Unit test for 32-bit and 64-bit high/low-bit operations. diff --git a/test/568-checker-onebit/src/Main.java b/test/568-checker-onebit/src/Main.java new file mode 100644 index 0000000000..7007c6a507 --- /dev/null +++ b/test/568-checker-onebit/src/Main.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +public class Main { + + /// CHECK-START: int Main.hi32(int) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerHighestOneBit + /// CHECK-DAG: Return [<<Result>>] + private static int hi32(int x) { + return Integer.highestOneBit(x); + } + + /// CHECK-START: int Main.lo32(int) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerLowestOneBit + /// CHECK-DAG: Return [<<Result>>] + private static int lo32(int x) { + return Integer.lowestOneBit(x); + } + + /// CHECK-START: long Main.hi64(long) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect intrinsic:LongHighestOneBit + /// CHECK-DAG: Return [<<Result>>] + private static long hi64(long x) { + return Long.highestOneBit(x); + } + + /// CHECK-START: long Main.lo64(long) intrinsics_recognition (after) + /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect intrinsic:LongLowestOneBit + /// CHECK-DAG: Return [<<Result>>] + private static long lo64(long x) { + return Long.lowestOneBit(x); + } + + public static void main(String args[]) { + expectEquals32(0x00000000, hi32(0x00000000)); + expectEquals32(0x00000000, lo32(0x00000000)); + expectEquals32(0x00010000, hi32(0x00010000)); + expectEquals32(0x00010000, lo32(0x00010000)); + expectEquals32(0x00800000, hi32(0x00FF0000)); + expectEquals32(0x00010000, lo32(0x00FF0000)); + expectEquals32(0x80000000, hi32(0xFFFFFFFF)); + expectEquals32(0x00000001, lo32(0xFFFFFFFF)); + + for (int i = 0; i < 32; i++) { + expectEquals32(1 << i, hi32(1 << i)); + expectEquals32(1 << i, lo32(1 << i)); + int expected = i < 29 ? 0x8 << i : 0x80000000; + expectEquals32(expected, hi32(0xF << i)); + expectEquals32(0x1 << i, lo32(0xF << i)); + } + + expectEquals64(0x0000000000000000L, hi64(0x0000000000000000L)); + expectEquals64(0x0000000000000000L, lo64(0x0000000000000000L)); + expectEquals64(0x0000000100000000L, hi64(0x0000000100000000L)); + expectEquals64(0x0000000100000000L, lo64(0x0000000100000000L)); + expectEquals64(0x0000008000000000L, hi64(0x000000FF00000000L)); + expectEquals64(0x0000000100000000L, lo64(0x000000FF00000000L)); + expectEquals64(0x8000000000000000L, hi64(0xFFFFFFFFFFFFFFFFL)); + expectEquals64(0x0000000000000001L, lo64(0xFFFFFFFFFFFFFFFFL)); + + for (int i = 0; i < 64; i++) { + expectEquals64(1L << i, hi64(1L << i)); + expectEquals64(1L << i, lo64(1L << i)); + long expected = i < 61 ? 0x8L << i : 0x8000000000000000L; + expectEquals64(expected, hi64(0xFL << i)); + expectEquals64(0x1L << i, lo64(0xFL << i)); + } + + System.out.println("passed"); + } + + private static void expectEquals32(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + private static void expectEquals64(long expected, long result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index 429af6a9e3..d6c29837b7 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -526,11 +526,7 @@ endif TEST_ART_BROKEN_OPTIMIZING_DEBUGGABLE_RUN_TESTS := # Tests that should fail in the read barrier configuration with the interpreter. -# 004: Occasional timeout: "TEST TIMED OUT!" (b/26786154). -# 141: Occasional failures: "Aborted" (b/25866001). -TEST_ART_BROKEN_INTERPRETER_READ_BARRIER_RUN_TESTS := \ - 004-ThreadStress \ - 141-class-unload +TEST_ART_BROKEN_INTERPRETER_READ_BARRIER_RUN_TESTS := # Tests that should fail in the read barrier configuration with the default (Quick) compiler (AOT). # Quick has no support for read barriers and punts to the interpreter, so this list is composed of @@ -540,7 +536,6 @@ TEST_ART_BROKEN_DEFAULT_READ_BARRIER_RUN_TESTS := \ $(TEST_ART_BROKEN_INTERPRETER_RUN_TESTS) # Tests that should fail in the read barrier configuration with the Optimizing compiler (AOT). -# 004: Occasional timeout: "TEST TIMED OUT!" (b/26786154). # 484: Baker's fast path based read barrier compiler instrumentation generates code containing # more parallel moves on x86, thus some Checker assertions may fail. # 527: On ARM64, the read barrier instrumentation does not support the HArm64IntermediateAddress @@ -548,18 +543,13 @@ TEST_ART_BROKEN_DEFAULT_READ_BARRIER_RUN_TESTS := \ # 537: Expects an array copy to be intrinsified on x86-64, but calling-on-slowpath intrinsics are # not yet handled in the read barrier configuration. TEST_ART_BROKEN_OPTIMIZING_READ_BARRIER_RUN_TESTS := \ - 004-ThreadStress \ 484-checker-register-hints \ 527-checker-array-access-split \ 537-checker-arraycopy # Tests that should fail in the read barrier configuration with JIT. -# 004: Occasional timeout: "TEST TIMED OUT!" (b/26786154). -# 141: Disabled because of intermittent failures on the ART Builtbot (b/25866001). # 496: Occasional timeout: "Fault message: timeout: the monitored command dumped core" (b/26786304). TEST_ART_BROKEN_JIT_READ_BARRIER_RUN_TESTS := \ - 004-ThreadStress \ - 141-class-unload \ 496-checker-inlining-and-class-loader ifeq ($(ART_USE_READ_BARRIER),true) diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar index e004b6cff4..8245ccfde5 100755 --- a/test/etc/run-test-jar +++ b/test/etc/run-test-jar @@ -74,6 +74,14 @@ while true; do fi ARGS="${ARGS} $1" shift + elif [ "x$1" = "x--args" ]; then + shift + if [ "x$1" = "x" ]; then + echo "$0 missing argument to --args" 1>&2 + exit 1 + fi + ARGS="${ARGS} $1" + shift elif [ "x$1" = "x-Xcompiler-option" ]; then shift option="$1" @@ -533,6 +541,7 @@ else cd $ANDROID_BUILD_TOP + rm -rf ${DEX_LOCATION}/dalvik-cache/ $mkdir_cmdline || exit 1 $dex2oat_cmdline || { echo "Dex2oat failed." >&2 ; exit 2; } |