Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 import annotations.BootstrapMethod;
     18 import annotations.CalledByIndy;
     19 import annotations.Constant;
     20 import java.lang.invoke.CallSite;
     21 import java.lang.invoke.ConstantCallSite;
     22 import java.lang.invoke.MethodHandle;
     23 import java.lang.invoke.MethodHandles;
     24 import java.lang.invoke.MethodType;
     25 import java.lang.invoke.WrongMethodTypeException;
     26 
     27 public class TestBadBootstrapArguments extends TestBase {
     28     private static CallSite bsm(
     29             MethodHandles.Lookup lookup,
     30             String methodName,
     31             MethodType methodType,
     32             int extraInt,
     33             String extraString)
     34             throws Throwable {
     35         System.out.print("bsm(");
     36         System.out.print(lookup.lookupClass());
     37         System.out.print(", ");
     38         System.out.print(methodName);
     39         System.out.print(", ");
     40         System.out.print(methodType);
     41         System.out.print(", ");
     42         System.out.print(extraInt);
     43         System.out.print(", ");
     44         System.out.print(extraString);
     45         System.out.println(")");
     46         MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType);
     47         return new ConstantCallSite(mh);
     48     }
     49 
     50     @CalledByIndy(
     51         bootstrapMethod =
     52                 @BootstrapMethod(
     53                     enclosingType = TestBadBootstrapArguments.class,
     54                     name = "bsm",
     55                     parameterTypes = {
     56                         MethodHandles.Lookup.class,
     57                         String.class,
     58                         MethodType.class,
     59                         int.class,
     60                         String.class
     61                     }
     62                 ),
     63         fieldOrMethodName = "happy",
     64         constantArgumentsForBootstrapMethod = {
     65             @Constant(intValue = -1),
     66             @Constant(stringValue = "very")
     67         }
     68     )
     69     private static void invokeHappy() {
     70         assertNotReached();
     71     }
     72 
     73     private static void happy() {
     74         System.out.println("happy");
     75     }
     76 
     77     // BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod)
     78     @CalledByIndy(
     79         bootstrapMethod =
     80                 @BootstrapMethod(
     81                     enclosingType = TestBadBootstrapArguments.class,
     82                     name = "bsm",
     83                     parameterTypes = {
     84                         MethodHandles.Lookup.class,
     85                         String.class,
     86                         MethodType.class,
     87                         int.class,
     88                         double.class
     89                     }
     90                 ),
     91         fieldOrMethodName = "wrongParameterTypes",
     92         constantArgumentsForBootstrapMethod = {
     93             @Constant(intValue = -1),
     94             @Constant(stringValue = "very")
     95         }
     96     )
     97     private static void invokeWrongParameterTypes() throws NoSuchMethodError {
     98         assertNotReached();
     99     }
    100 
    101     private static void wrongParameterTypes() {
    102         System.out.println("wrongParameterTypes");
    103     }
    104 
    105     // BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod)
    106     // (missing constantArgumentTypes))
    107     @CalledByIndy(
    108         bootstrapMethod =
    109                 @BootstrapMethod(
    110                     enclosingType = TestBadBootstrapArguments.class,
    111                     name = "bsm",
    112                     parameterTypes = {
    113                         MethodHandles.Lookup.class,
    114                         String.class,
    115                         MethodType.class,
    116                         int.class,
    117                         double.class
    118                     }
    119                 ),
    120         fieldOrMethodName = "missingParameterTypes",
    121         constantArgumentsForBootstrapMethod = {}
    122     )
    123     private static void invokeMissingParameterTypes() throws NoSuchMethodError {
    124         assertNotReached();
    125     }
    126 
    127     private static void missingParameterTypes() {
    128         System.out.println("missingParameterTypes");
    129     }
    130 
    131     // BootstrapMethod.parameterTypes != parameterTypesOf(constantArgumentsForBootstrapMethod):
    132     // extra constant present
    133     @CalledByIndy(
    134         bootstrapMethod =
    135                 @BootstrapMethod(
    136                     enclosingType = TestBadBootstrapArguments.class,
    137                     name = "bsm",
    138                     parameterTypes = {
    139                         MethodHandles.Lookup.class,
    140                         String.class,
    141                         MethodType.class,
    142                         int.class,
    143                         String.class
    144                     }
    145                 ),
    146         fieldOrMethodName = "extraArguments",
    147         constantArgumentsForBootstrapMethod = {
    148             @Constant(intValue = 1),
    149             @Constant(stringValue = "2"),
    150             @Constant(intValue = 3)
    151         }
    152     )
    153     private static void invokeExtraArguments() {
    154         assertNotReached();
    155     }
    156 
    157     private static void extraArguments() {
    158         System.out.println("extraArguments");
    159     }
    160 
    161     // constantArgumentTypes do not correspond to expected parameter types
    162     @CalledByIndy(
    163         bootstrapMethod =
    164                 @BootstrapMethod(
    165                     enclosingType = TestBadBootstrapArguments.class,
    166                     name = "bsm",
    167                     parameterTypes = {
    168                         MethodHandles.Lookup.class,
    169                         String.class,
    170                         MethodType.class,
    171                         int.class,
    172                         String.class
    173                     }
    174                 ),
    175         fieldOrMethodName = "wrongArguments",
    176         constantArgumentsForBootstrapMethod = {
    177             @Constant(stringValue = "1"),
    178             @Constant(doubleValue = Math.PI)
    179         }
    180     )
    181     private static void invokeWrongArguments() {
    182         assertNotReached();
    183     }
    184 
    185     private static void wrongArguments() {
    186         System.out.println("wrongArguments");
    187     }
    188 
    189     // constantArgumentTypes do not correspond to expected parameter types
    190     @CalledByIndy(
    191         bootstrapMethod =
    192                 @BootstrapMethod(
    193                     enclosingType = TestBadBootstrapArguments.class,
    194                     name = "bsm",
    195                     parameterTypes = {
    196                         MethodHandles.Lookup.class,
    197                         String.class,
    198                         MethodType.class,
    199                         int.class,
    200                         String.class
    201                     }
    202                 ),
    203         fieldOrMethodName = "wrongArgumentsAgain",
    204         constantArgumentsForBootstrapMethod = {
    205             @Constant(doubleValue = Math.PI),
    206             @Constant(stringValue = "pie")
    207         }
    208     )
    209     private static void invokeWrongArgumentsAgain() {
    210         assertNotReached();
    211     }
    212 
    213     private static void wrongArgumentsAgain() {
    214         System.out.println("wrongArgumentsAgain");
    215     }
    216 
    217     // Primitive argument types not supported {Z, B, C, S}.
    218     private static CallSite bsmZBCS(
    219             MethodHandles.Lookup lookup,
    220             String methodName,
    221             MethodType methodType,
    222             boolean extraArg0,
    223             byte extraArg1,
    224             char extraArg2,
    225             short extraArg3)
    226             throws Throwable {
    227         assertNotReached();
    228         return null;
    229     }
    230 
    231     // Arguments are narrower than supported.
    232     @CalledByIndy(
    233         bootstrapMethod =
    234                 @BootstrapMethod(
    235                     enclosingType = TestBadBootstrapArguments.class,
    236                     name = "bsmZBCS",
    237                     parameterTypes = {
    238                         MethodHandles.Lookup.class,
    239                         String.class,
    240                         MethodType.class,
    241                         boolean.class,
    242                         byte.class,
    243                         char.class,
    244                         short.class
    245                     }
    246                 ),
    247         fieldOrMethodName = "narrowArguments",
    248         constantArgumentsForBootstrapMethod = {
    249             @Constant(booleanValue = true),
    250             @Constant(byteValue = Byte.MAX_VALUE),
    251             @Constant(charValue = 'A'),
    252             @Constant(shortValue = Short.MIN_VALUE)
    253         }
    254     )
    255     private static void invokeNarrowArguments() {
    256         assertNotReached();
    257     }
    258 
    259     private static void narrowArguments() {
    260         assertNotReached();
    261     }
    262 
    263     private static CallSite bsmDJ(
    264             MethodHandles.Lookup lookup,
    265             String methodName,
    266             MethodType methodType,
    267             double extraArg0,
    268             long extraArg1)
    269             throws Throwable {
    270         System.out.print("bsmDJ(..., ");
    271         System.out.print(extraArg0);
    272         System.out.print(", ");
    273         System.out.print(extraArg1);
    274         System.out.println(")");
    275         MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType);
    276         return new ConstantCallSite(mh);
    277     }
    278 
    279     // Arguments need widening to parameter types.
    280     @CalledByIndy(
    281         bootstrapMethod =
    282                 @BootstrapMethod(
    283                     enclosingType = TestBadBootstrapArguments.class,
    284                     name = "bsmDJ",
    285                     parameterTypes = {
    286                         MethodHandles.Lookup.class,
    287                         String.class,
    288                         MethodType.class,
    289                         double.class,
    290                         long.class
    291                     }
    292                 ),
    293         fieldOrMethodName = "wideningArguments",
    294         constantArgumentsForBootstrapMethod = {
    295             @Constant(doubleValue = Double.MAX_VALUE),
    296             @Constant(intValue = Integer.MAX_VALUE)
    297         }
    298     )
    299     private static void invokeWideningArguments() {
    300         assertNotReached();
    301     }
    302 
    303     private static void wideningArguments() {
    304         System.out.println("wideningArguments");
    305     }
    306 
    307     private static CallSite bsmDoubleLong(
    308             MethodHandles.Lookup lookup,
    309             String methodName,
    310             MethodType methodType,
    311             Double extraArg0,
    312             Long extraArg1)
    313             throws Throwable {
    314         System.out.print("bsmDoubleLong(..., ");
    315         System.out.print(extraArg0);
    316         System.out.print(", ");
    317         System.out.print(extraArg1);
    318         System.out.println(")");
    319         MethodHandle mh = lookup.findStatic(lookup.lookupClass(), methodName, methodType);
    320         return new ConstantCallSite(mh);
    321     }
    322 
    323     // Arguments need boxing to parameter types
    324     @CalledByIndy(
    325         bootstrapMethod =
    326                 @BootstrapMethod(
    327                     enclosingType = TestBadBootstrapArguments.class,
    328                     name = "bsmDoubleLong",
    329                     parameterTypes = {
    330                         MethodHandles.Lookup.class,
    331                         String.class,
    332                         MethodType.class,
    333                         Double.class,
    334                         Long.class
    335                     }
    336                 ),
    337         fieldOrMethodName = "boxingArguments",
    338         constantArgumentsForBootstrapMethod = {
    339             @Constant(doubleValue = Double.MAX_VALUE),
    340             @Constant(longValue = Long.MAX_VALUE)
    341         }
    342     )
    343     private static void invokeBoxingArguments() {
    344         assertNotReached();
    345     }
    346 
    347     private static void boxingArguments() {
    348         System.out.println("boxingArguments");
    349     }
    350 
    351     // Arguments need widening and boxing to parameter types
    352     @CalledByIndy(
    353         bootstrapMethod =
    354                 @BootstrapMethod(
    355                     enclosingType = TestBadBootstrapArguments.class,
    356                     name = "bsmDoubleLong",
    357                     parameterTypes = {
    358                         MethodHandles.Lookup.class,
    359                         String.class,
    360                         MethodType.class,
    361                         Double.class,
    362                         Long.class
    363                     }
    364                 ),
    365         fieldOrMethodName = "wideningBoxingArguments",
    366         constantArgumentsForBootstrapMethod = {
    367             @Constant(floatValue = Float.MAX_VALUE),
    368             @Constant(longValue = Integer.MAX_VALUE)
    369         }
    370     )
    371     private static void invokeWideningBoxingArguments() {
    372         assertNotReached();
    373     }
    374 
    375     private static void wideningBoxingArguments() {
    376         System.out.println("wideningBoxingArguments");
    377     }
    378 
    379     static void bsmReturningVoid(MethodHandles.Lookup lookup, String name, MethodType type) {
    380         System.out.println("bsm returning void value.");
    381     }
    382 
    383     @CalledByIndy(
    384         bootstrapMethod =
    385                 @BootstrapMethod(
    386                     enclosingType = TestBadBootstrapArguments.class,
    387                     name = "bsmReturningVoid",
    388                     parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
    389                     returnType = void.class
    390                 ),
    391         fieldOrMethodName = "voidReturnType"
    392     )
    393     private static void invokeVoidReturnType() {
    394         assertNotReached();
    395     }
    396 
    397     private static void voidReturnType() {
    398         assertNotReached();
    399     }
    400 
    401     static Object bsmReturningObject(MethodHandles.Lookup lookup, String name, MethodType type) {
    402         System.out.println("bsm returning Object value.");
    403         return new Object();
    404     }
    405 
    406     @CalledByIndy(
    407         bootstrapMethod =
    408                 @BootstrapMethod(
    409                     enclosingType = TestBadBootstrapArguments.class,
    410                     name = "bsmReturningObject",
    411                     parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
    412                     returnType = Object.class
    413                 ),
    414         fieldOrMethodName = "ObjectReturnType"
    415     )
    416     private static void invokeObjectReturnType() {
    417         assertNotReached();
    418     }
    419 
    420     private static void objectReturnType() {
    421         assertNotReached();
    422     }
    423 
    424     static Integer bsmReturningInteger(MethodHandles.Lookup lookup, String name, MethodType type) {
    425         System.out.println("bsm returning Integer value.");
    426         return Integer.valueOf(3);
    427     }
    428 
    429     @CalledByIndy(
    430         bootstrapMethod =
    431                 @BootstrapMethod(
    432                     enclosingType = TestBadBootstrapArguments.class,
    433                     name = "bsmReturningInteger",
    434                     parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
    435                     returnType = Integer.class
    436                 ),
    437         fieldOrMethodName = "integerReturnType"
    438     )
    439     private static void invokeIntegerReturnType() {
    440         assertNotReached();
    441     }
    442 
    443     private static void integerReturnType() {
    444         assertNotReached();
    445     }
    446 
    447     static class TestersConstantCallSite extends ConstantCallSite {
    448         public TestersConstantCallSite(MethodHandle mh) {
    449             super(mh);
    450         }
    451     }
    452 
    453     static TestersConstantCallSite bsmReturningTestersConstantCallsite(
    454             MethodHandles.Lookup lookup, String name, MethodType type) throws Throwable {
    455         return new TestersConstantCallSite(lookup.findStatic(lookup.lookupClass(), name, type));
    456     }
    457 
    458     @CalledByIndy(
    459         bootstrapMethod =
    460                 @BootstrapMethod(
    461                     enclosingType = TestBadBootstrapArguments.class,
    462                     name = "bsmReturningTestersConstantCallsite",
    463                     parameterTypes = {MethodHandles.Lookup.class, String.class, MethodType.class},
    464                     returnType = TestersConstantCallSite.class
    465                 ),
    466         fieldOrMethodName = "sayHello"
    467     )
    468     private static void invokeViaCustomCallSiteClass() {
    469         assertNotReached();
    470     }
    471 
    472     private static void sayHello() {
    473         System.out.println("Hello!");
    474     }
    475 
    476     static void test() {
    477         System.out.println("TestBadBootstrapArguments");
    478         invokeHappy();
    479         try {
    480             invokeWrongParameterTypes();
    481             assertNotReached();
    482         } catch (NoSuchMethodError expected) {
    483             System.out.print("invokeWrongParameterTypes => ");
    484             System.out.println(expected.getClass());
    485         }
    486         try {
    487             invokeMissingParameterTypes();
    488             assertNotReached();
    489         } catch (NoSuchMethodError expected) {
    490             System.out.print("invokeMissingParameterTypes => ");
    491             System.out.println(expected.getClass());
    492         }
    493         try {
    494             invokeExtraArguments();
    495             assertNotReached();
    496         } catch (BootstrapMethodError expected) {
    497             assertEquals(WrongMethodTypeException.class, expected.getCause().getClass());
    498             System.out.print("invokeExtraArguments => ");
    499             System.out.print(expected.getClass());
    500             System.out.print(" => ");
    501             System.out.println(expected.getCause().getClass());
    502         }
    503         try {
    504             invokeWrongArguments();
    505             assertNotReached();
    506         } catch (BootstrapMethodError expected) {
    507             assertEquals(ClassCastException.class, expected.getCause().getClass());
    508             System.out.print("invokeWrongArguments => ");
    509             System.out.print(expected.getClass());
    510             System.out.print(" => ");
    511             System.out.println(expected.getCause().getClass());
    512         }
    513         try {
    514             invokeWrongArguments();
    515             assertNotReached();
    516         } catch (BootstrapMethodError expected) {
    517             assertEquals(ClassCastException.class, expected.getCause().getClass());
    518             System.out.print("invokeWrongArguments => ");
    519             System.out.print(expected.getClass());
    520             System.out.print(" => ");
    521             System.out.println(expected.getCause().getClass());
    522         }
    523         try {
    524             invokeWrongArgumentsAgain();
    525             assertNotReached();
    526         } catch (BootstrapMethodError expected) {
    527             assertEquals(ClassCastException.class, expected.getCause().getClass());
    528             System.out.print("invokeWrongArgumentsAgain => ");
    529             System.out.print(expected.getClass());
    530             System.out.print(" => ");
    531             System.out.println(expected.getCause().getClass());
    532         }
    533         try {
    534             invokeNarrowArguments();
    535             assertNotReached();
    536         } catch (BootstrapMethodError expected) {
    537             assertEquals(ClassCastException.class, expected.getCause().getClass());
    538             System.out.print("invokeNarrowArguments => ");
    539             System.out.print(expected.getClass());
    540             System.out.print(" => ");
    541             System.out.println(expected.getCause().getClass());
    542         }
    543         invokeWideningArguments();
    544         invokeBoxingArguments();
    545         try {
    546             invokeWideningBoxingArguments();
    547             assertNotReached();
    548         } catch (BootstrapMethodError expected) {
    549             System.out.print("invokeWideningBoxingArguments => ");
    550             System.out.print(expected.getClass());
    551             System.out.print(" => ");
    552             System.out.println(expected.getCause().getClass());
    553         }
    554         try {
    555             invokeVoidReturnType();
    556             assertNotReached();
    557         } catch (BootstrapMethodError expected) {
    558             System.out.print("invokeVoidReturnType() => ");
    559             System.out.print(expected.getClass());
    560             System.out.print(" => ");
    561             System.out.println(expected.getCause().getClass());
    562         }
    563         try {
    564             invokeObjectReturnType();
    565             assertNotReached();
    566         } catch (BootstrapMethodError expected) {
    567             System.out.print("invokeObjectReturnType() => ");
    568             System.out.print(expected.getClass());
    569             System.out.print(" => ");
    570             System.out.println(expected.getCause().getClass());
    571         }
    572         try {
    573             invokeIntegerReturnType();
    574             assertNotReached();
    575         } catch (BootstrapMethodError expected) {
    576             System.out.print("invokeIntegerReturnType() => ");
    577             System.out.print(expected.getClass());
    578             System.out.print(" => ");
    579             System.out.println(expected.getCause().getClass());
    580         }
    581         invokeViaCustomCallSiteClass();
    582     }
    583 }
    584