1 /*
2  * Copyright (C) 2016 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 package libcore.java.lang.reflect;
18 
19 import junit.framework.TestCase;
20 
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.InputStream;
24 import java.lang.annotation.ElementType;
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.lang.annotation.Target;
28 import java.lang.reflect.Constructor;
29 import java.lang.reflect.Executable;
30 import java.lang.reflect.MalformedParametersException;
31 import java.lang.reflect.Method;
32 import java.lang.reflect.Modifier;
33 import java.lang.reflect.Parameter;
34 import java.text.NumberFormat;
35 import java.util.Arrays;
36 import java.util.concurrent.Callable;
37 import java.util.function.Function;
38 import libcore.io.Streams;
39 
40 import dalvik.system.PathClassLoader;
41 
42 /**
43  * Tests for {@link Parameter}. For annotation-related tests see
44  * {@link libcore.java.lang.reflect.annotations.AnnotatedElementParameterTest} and
45  * {@link libcore.java.lang.reflect.annotations.ExecutableParameterTest}.
46  *
47  * <p>Tests suffixed with _withMetadata() require parameter metadata compiled in to work properly.
48  * These are handled by loading pre-compiled .dex files.
49  * See also {@link DependsOnParameterMetadata}.
50  */
51 public class ParameterTest extends TestCase {
52 
53     /**
54      * A ClassLoader that can be used to load the
55      * libcore.java.lang.reflect.parameter.ParameterMetadataTestClasses class and its nested
56      * classes. The loaded classes has valid metadata that could be created by a valid Android
57      * compiler.
58      */
59     private ClassLoader classesWithMetadataClassLoader;
60 
61     /**
62      * A ClassLoader that can be used to load the
63      * libcore.java.lang.reflect.parameter.MetadataVariations class.
64      * The loaded class has invalid metadata that could not be created by a valid Android
65      * compiler.
66      */
67     private ClassLoader metadataVariationsClassLoader;
68 
69     @Override
setUp()70     public void setUp() throws Exception {
71         super.setUp();
72         File dexDir = File.createTempFile("dexDir", "");
73         assertTrue(dexDir.delete());
74         assertTrue(dexDir.mkdirs());
75 
76         classesWithMetadataClassLoader =
77                 createClassLoaderForDexResource(dexDir, "parameter_metadata_test_classes.dex");
78         metadataVariationsClassLoader =
79                 createClassLoaderForDexResource(dexDir, "metadata_variations.dex");
80     }
81 
82     /**
83      * A source annotation used to mark code below with behavior that is highly dependent on
84      * parameter metadata. It is intended to bring readers here for the following:
85      *
86      * <p>Unless the compiler supports (and is configured to enable) storage of metadata
87      * for parameters, the runtime does not have access to the parameter name from the source and
88      * some modifier information like "implicit" (AKA "mandated"), "synthetic" and "final".
89      *
90      * <p>This test class is expected to be compiled <em>without</em> requesting that the metadata
91      * be compiled in. dex files that contains classes with metadata are loaded in setUp() and
92      * used from the tests suffixed with "_withMetadata".
93      */
94     @Retention(RetentionPolicy.SOURCE)
95     @Target(ElementType.METHOD)
96     private @interface DependsOnParameterMetadata {}
97 
98     private static class SingleParameter {
99         @SuppressWarnings("unused")
SingleParameter(String p0)100         SingleParameter(String p0) {}
101 
102         @SuppressWarnings("unused")
oneParameter(String p0)103         void oneParameter(String p0) {}
104     }
105 
testSingleParameterConstructor()106     public void testSingleParameterConstructor() throws Exception {
107         Constructor<?> constructor = SingleParameter.class.getDeclaredConstructor(String.class);
108         checkSingleStringParameter(constructor);
109     }
110 
testSingleParameterMethod()111     public void testSingleParameterMethod() throws Exception {
112         Method method = SingleParameter.class.getDeclaredMethod("oneParameter", String.class);
113         checkSingleStringParameter(method);
114     }
115 
checkSingleStringParameter(Executable executable)116     private static void checkSingleStringParameter(Executable executable) {
117         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
118         helper.checkStandardParametersBehavior()
119                 .checkParametersToString("[java.lang.String arg0]")
120                 .checkParametersMetadataNotAvailable()
121                 .checkParametersNoVarArgs();
122 
123         helper.getParameterTestHelper(0)
124                 .checkGetType(String.class)
125                 .checkGetParameterizedType("class java.lang.String");
126     }
127 
testSingleParameterConstructor_withMetadata()128     public void testSingleParameterConstructor_withMetadata() throws Exception {
129         Class<?> clazz = loadTestInnerClassWithMetadata("SingleParameter");
130         Constructor<?> constructor  = clazz.getDeclaredConstructor(String.class);
131         checkSingleStringParameter_withMetadata(constructor);
132     }
133 
testSingleParameterMethod_withMetadata()134     public void testSingleParameterMethod_withMetadata() throws Exception {
135         Class<?> clazz = loadTestInnerClassWithMetadata("SingleParameter");
136         Method method = clazz.getDeclaredMethod("oneParameter", String.class);
137         checkSingleStringParameter_withMetadata(method);
138     }
139 
checkSingleStringParameter_withMetadata(Executable executable)140     private static void checkSingleStringParameter_withMetadata(Executable executable) {
141         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
142         helper.checkStandardParametersBehavior()
143                 .checkParametersToString("[java.lang.String p0]")
144                 .checkParametersNoVarArgs();
145 
146         helper.getParameterTestHelper(0)
147                 .checkGetType(String.class)
148                 .checkName(true /* expectedNameIsPresent */, "p0")
149                 .checkModifiers(0)
150                 .checkImplicitAndSynthetic(false, false)
151                 .checkGetParameterizedType("class java.lang.String");
152     }
153 
154     private static class GenericParameter {
155         @SuppressWarnings("unused")
GenericParameter(Function<String, Integer> p0)156         GenericParameter(Function<String, Integer> p0) {}
157 
158         @SuppressWarnings("unused")
genericParameter(Function<String, Integer> p0)159         void genericParameter(Function<String, Integer> p0) {}
160     }
161 
testGenericParameterConstructor()162     public void testGenericParameterConstructor() throws Exception {
163         Constructor<?> constructor = GenericParameter.class.getDeclaredConstructor(Function.class);
164         checkGenericParameter(constructor);
165     }
166 
testGenericParameterMethod()167     public void testGenericParameterMethod() throws Exception {
168         Method method = GenericParameter.class.getDeclaredMethod(
169                 "genericParameter", Function.class);
170         checkGenericParameter(method);
171     }
172 
checkGenericParameter(Executable executable)173     private static void checkGenericParameter(Executable executable) {
174         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
175         helper.checkStandardParametersBehavior()
176                 .checkParametersToString(
177                         "[java.util.function.Function<java.lang.String, java.lang.Integer> arg0]")
178                 .checkParametersMetadataNotAvailable()
179                 .checkParametersNoVarArgs();
180 
181         helper.getParameterTestHelper(0)
182                 .checkGetType(Function.class)
183                 .checkGetParameterizedType(
184                         "java.util.function.Function<java.lang.String, java.lang.Integer>");
185     }
186 
testGenericParameterConstructor_withMetadata()187     public void testGenericParameterConstructor_withMetadata() throws Exception {
188         Class<?> clazz = loadTestInnerClassWithMetadata("GenericParameter");
189         Constructor<?> constructor = clazz.getDeclaredConstructor(Function.class);
190         checkGenericParameter_withMetadata(constructor);
191     }
192 
testGenericParameterMethod_withMetadata()193     public void testGenericParameterMethod_withMetadata() throws Exception {
194         Class<?> clazz = loadTestInnerClassWithMetadata("GenericParameter");
195         Method method = clazz.getDeclaredMethod("genericParameter", Function.class);
196         checkGenericParameter_withMetadata(method);
197     }
198 
checkGenericParameter_withMetadata(Executable executable)199     private static void checkGenericParameter_withMetadata(Executable executable) {
200         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
201         helper.checkStandardParametersBehavior()
202                 .checkParametersToString(
203                         "[java.util.function.Function<java.lang.String, java.lang.Integer> p0]")
204                 .checkParametersNoVarArgs();
205 
206         helper.getParameterTestHelper(0)
207                 .checkGetType(Function.class)
208                 .checkName(true /* expectedNameIsPresent */, "p0")
209                 .checkModifiers(0)
210                 .checkImplicitAndSynthetic(false, false)
211                 .checkGetParameterizedType(
212                         "java.util.function.Function<java.lang.String, java.lang.Integer>");
213     }
214 
215     private static class TwoParameters {
216         @SuppressWarnings("unused")
TwoParameters(String p0, Integer p1)217         TwoParameters(String p0, Integer p1) {}
218         @SuppressWarnings("unused")
twoParameters(String p0, Integer p1)219         void twoParameters(String p0, Integer p1) {}
220     }
221 
testTwoParameterConstructor()222     public void testTwoParameterConstructor() throws Exception {
223         Constructor<?> constructor =
224                 TwoParameters.class.getDeclaredConstructor(String.class, Integer.class);
225         checkTwoParameters(constructor);
226     }
227 
testTwoParameterMethod()228     public void testTwoParameterMethod() throws Exception {
229         Method method = TwoParameters.class.getDeclaredMethod(
230                 "twoParameters", String.class, Integer.class);
231         checkTwoParameters(method);
232     }
233 
checkTwoParameters(Executable executable)234     private static void checkTwoParameters(Executable executable) {
235         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
236         helper.checkStandardParametersBehavior()
237                 .checkParametersToString("[java.lang.String arg0, java.lang.Integer arg1]")
238                 .checkParametersMetadataNotAvailable()
239                 .checkParametersNoVarArgs();
240 
241         helper.getParameterTestHelper(0)
242                 .checkGetType(String.class)
243                 .checkGetParameterizedType("class java.lang.String");
244 
245         helper.getParameterTestHelper(1)
246                 .checkGetType(Integer.class)
247                 .checkGetParameterizedType("class java.lang.Integer");
248     }
249 
testTwoParameterConstructor_withMetadata()250     public void testTwoParameterConstructor_withMetadata() throws Exception {
251         Class<?> clazz = loadTestInnerClassWithMetadata("TwoParameters");
252         Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
253         checkTwoParameters_withMetadata(constructor);
254     }
255 
testTwoParameterMethod_withMetadata()256     public void testTwoParameterMethod_withMetadata() throws Exception {
257         Class<?> clazz = loadTestInnerClassWithMetadata("TwoParameters");
258         Method method = clazz.getDeclaredMethod("twoParameters", String.class, Integer.class);
259         checkTwoParameters_withMetadata(method);
260     }
261 
checkTwoParameters_withMetadata(Executable executable)262     private static void checkTwoParameters_withMetadata(Executable executable) {
263         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
264         helper.checkStandardParametersBehavior()
265                 .checkParametersToString("[java.lang.String p0, java.lang.Integer p1]")
266                 .checkParametersNoVarArgs();
267 
268         helper.getParameterTestHelper(0)
269                 .checkGetType(String.class)
270                 .checkName(true /* expectedNameIsPresent */, "p0")
271                 .checkModifiers(0)
272                 .checkImplicitAndSynthetic(false, false)
273                 .checkGetParameterizedType("class java.lang.String");
274 
275         helper.getParameterTestHelper(1)
276                 .checkGetType(Integer.class)
277                 .checkName(true /* expectedNameIsPresent */, "p1")
278                 .checkModifiers(0)
279                 .checkImplicitAndSynthetic(false, false)
280                 .checkGetParameterizedType("class java.lang.Integer");
281     }
282 
283     private static class FinalParameter {
284         @SuppressWarnings("unused")
FinalParameter(final String p0)285         FinalParameter(final String p0) {}
286         @SuppressWarnings("unused")
finalParameter(final String p0)287         void finalParameter(final String p0) {}
288     }
289 
testFinalParameterConstructor()290     public void testFinalParameterConstructor() throws Exception {
291         Constructor<?> constructor = FinalParameter.class.getDeclaredConstructor(String.class);
292         checkFinalParameter(constructor);
293     }
294 
testFinalParameterMethod()295     public void testFinalParameterMethod() throws Exception {
296         Method method = FinalParameter.class.getDeclaredMethod("finalParameter", String.class);
297         checkFinalParameter(method);
298     }
299 
checkFinalParameter(Executable executable)300     private static void checkFinalParameter(Executable executable) {
301         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
302         helper.checkStandardParametersBehavior()
303                 .checkParametersToString("[java.lang.String arg0]")
304                 .checkParametersMetadataNotAvailable()
305                 .checkParametersNoVarArgs();
306 
307         helper.getParameterTestHelper(0)
308                 .checkGetType(String.class)
309                 .checkGetParameterizedType("class java.lang.String");
310     }
311 
testFinalParameterConstructor_withMetdata()312     public void testFinalParameterConstructor_withMetdata() throws Exception {
313         Class<?> clazz = loadTestInnerClassWithMetadata("FinalParameter");
314         Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
315         checkFinalParameter_withMetadata(constructor);
316     }
317 
testFinalParameterMethod_withMetdata()318     public void testFinalParameterMethod_withMetdata() throws Exception {
319         Class<?> clazz = loadTestInnerClassWithMetadata("FinalParameter");
320         Method method = clazz.getDeclaredMethod("finalParameter", String.class);
321         checkFinalParameter_withMetadata(method);
322     }
323 
checkFinalParameter_withMetadata(Executable executable)324     private static void checkFinalParameter_withMetadata(Executable executable) {
325         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
326         helper.checkStandardParametersBehavior()
327                 .checkParametersToString("[final java.lang.String p0]")
328                 .checkParametersNoVarArgs();
329 
330         helper.getParameterTestHelper(0)
331                 .checkGetType(String.class)
332                 .checkName(true /* expectedNameIsPresent */, "p0")
333                 .checkModifiers(Modifier.FINAL)
334                 .checkImplicitAndSynthetic(false, false)
335                 .checkGetParameterizedType("class java.lang.String");
336     }
337 
338     /**
339      * An inner class, used for checking compiler-inserted parameters: The first parameter is an
340      * instance of the surrounding class.
341      */
342     private class InnerClass {
343         @SuppressWarnings("unused")
InnerClass()344         public InnerClass() {}
345         @SuppressWarnings("unused")
InnerClass(String p1)346         public InnerClass(String p1) {}
347         @SuppressWarnings("unused")
InnerClass(Function<String, Integer> p1)348         public InnerClass(Function<String, Integer> p1) {}
349     }
350 
testInnerClassSingleParameter()351     public void testInnerClassSingleParameter() throws Exception {
352         Class<?> outerClass = ParameterTest.class;
353         Class<?> innerClass = InnerClass.class;
354         Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
355 
356         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
357         helper.checkStandardParametersBehavior()
358                 .checkParametersToString("[" + outerClass.getName() + " arg0]")
359                 .checkParametersMetadataNotAvailable()
360                 .checkParametersNoVarArgs();
361 
362         helper.getParameterTestHelper(0)
363                 .checkGetType(outerClass)
364                 .checkGetParameterizedType("class " + outerClass.getName() + "");
365     }
366 
testInnerClassSingleParameter_withMetadata()367     public void testInnerClassSingleParameter_withMetadata() throws Exception {
368         Class<?> outerClass = loadTestOuterClassWithMetadata();
369         Class<?> innerClass = loadTestInnerClassWithMetadata("InnerClass");
370         Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
371 
372         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
373         helper.checkStandardParametersBehavior()
374                 .checkParametersToString("[final " + outerClass.getName() + " this$0]")
375                 .checkParametersNoVarArgs();
376 
377         helper.getParameterTestHelper(0)
378                 .checkGetType(outerClass)
379                 .checkName(true /* expectedNameIsPresent */, "this$0")
380                 .checkModifiers(32784) // 32784 == Modifier.MANDATED & Modifier.FINAL
381                 .checkImplicitAndSynthetic(true, false)
382                 .checkGetParameterizedType("class " + outerClass.getName());
383     }
384 
testInnerClassTwoParameters()385     public void testInnerClassTwoParameters() throws Exception {
386         Class<?> outerClass = ParameterTest.class;
387         Class<?> innerClass = InnerClass.class;
388         Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass, String.class);
389 
390         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
391         helper.checkStandardParametersBehavior()
392                 .checkParametersToString(
393                         "[" + outerClass.getName() + " arg0, java.lang.String arg1]")
394                 .checkParametersMetadataNotAvailable()
395                 .checkParametersNoVarArgs();
396 
397         helper.getParameterTestHelper(0)
398                 .checkGetType(outerClass)
399                 .checkGetParameterizedType("class " + outerClass.getName());
400 
401         helper.getParameterTestHelper(1)
402                 .checkGetType(String.class)
403                 .checkGetParameterizedType("class java.lang.String");
404     }
405 
testInnerClassTwoParameters_withMetadata()406     public void testInnerClassTwoParameters_withMetadata() throws Exception {
407         Class<?> outerClass = loadTestOuterClassWithMetadata();
408         Class<?> innerClass = loadTestInnerClassWithMetadata("InnerClass");
409         Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass, String.class);
410 
411         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
412         helper.checkStandardParametersBehavior()
413                 .checkParametersToString(
414                         "[final " + outerClass.getName() + " this$0, java.lang.String p1]")
415                 .checkParametersNoVarArgs();
416 
417         helper.getParameterTestHelper(0)
418                 .checkName(true /* expectedNameIsPresent */, "this$0")
419                 .checkModifiers(32784) // 32784 == Modifier.MANDATED & Modifier.FINAL
420                 .checkImplicitAndSynthetic(true, false)
421                 .checkGetType(outerClass)
422                 .checkGetParameterizedType("class " + outerClass.getName() + "");
423 
424         helper.getParameterTestHelper(1)
425                 .checkName(true /* expectedNameIsPresent */, "p1")
426                 .checkModifiers(0)
427                 .checkImplicitAndSynthetic(false, false)
428                 .checkGetType(String.class)
429                 .checkGetParameterizedType("class java.lang.String");
430     }
431 
testInnerClassGenericParameter()432     public void testInnerClassGenericParameter() throws Exception {
433         Class<?> outerClass = ParameterTest.class;
434         Class<?> innerClass = InnerClass.class;
435         Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass, Function.class);
436 
437         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
438         helper.checkStandardParametersBehavior()
439                 .checkParametersToString(
440                         "[" + outerClass.getName() + " arg0, java.util.function.Function arg1]")
441                 .checkParametersMetadataNotAvailable()
442                 .checkParametersNoVarArgs();
443 
444         helper.getParameterTestHelper(0)
445                 .checkGetType(outerClass)
446                 .checkGetParameterizedType("class " + outerClass.getName() + "");
447 
448         helper.getParameterTestHelper(1)
449                 .checkGetType(Function.class)
450                 .checkGetParameterizedType("interface java.util.function.Function");
451 
452         // The non-genericised string above is probably the result of a spec bug due to a mismatch
453         // between the generic signature for the constructor (which suggests a single parameter)
454         // and the actual parameters (which suggests two). In the absence of parameter metadata
455         // to identify the synthetic parameter the code reverts to using non-Signature (type erased)
456         // information.
457     }
458 
testInnerClassGenericParameter_withMetadata()459     public void testInnerClassGenericParameter_withMetadata() throws Exception {
460         Class<?> outerClass = loadTestOuterClassWithMetadata();
461         Class<?> innerClass = loadTestInnerClassWithMetadata("InnerClass");
462         Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass, Function.class);
463 
464         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
465         helper.checkStandardParametersBehavior()
466                 .checkParametersToString("[final " + outerClass.getName() + " this$0, "
467                         + "java.util.function.Function<java.lang.String, java.lang.Integer> p1]")
468                 .checkParametersNoVarArgs();
469 
470         helper.getParameterTestHelper(0)
471                 .checkName(true /* expectedNameIsPresent */, "this$0")
472                 .checkModifiers(32784) // 32784 == Modifier.MANDATED & Modifier.FINAL
473                 .checkImplicitAndSynthetic(true, false)
474                 .checkGetType(outerClass)
475                 .checkGetParameterizedType("class " + outerClass.getName() + "");
476 
477         helper.getParameterTestHelper(1)
478                 .checkName(true /* expectedNameIsPresent */, "p1")
479                 .checkModifiers(0)
480                 .checkImplicitAndSynthetic(false, false)
481                 .checkGetType(Function.class)
482                 .checkGetParameterizedType(
483                         "java.util.function.Function<java.lang.String, java.lang.Integer>");
484     }
485 
486     @SuppressWarnings("unused")
487     enum TestEnum { ONE, TWO }
488 
489     /**
490      * Enums are a documented example of a type of class with synthetic constructor parameters and
491      * generated methods. This test may be brittle as it may rely on the compiler's implementation
492      * of enums.
493      */
testEnumConstructor()494     public void testEnumConstructor() throws Exception {
495         Constructor<?> constructor = TestEnum.class.getDeclaredConstructor(String.class, int.class);
496 
497         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
498         helper.checkStandardParametersBehavior()
499                 .checkParametersToString("[java.lang.String arg0, int arg1]")
500                 .checkParametersNoVarArgs();
501 
502         helper.getParameterTestHelper(0)
503                 .checkGetType(String.class)
504                 .checkGetParameterizedType("class java.lang.String");
505 
506         helper.getParameterTestHelper(1)
507                 .checkGetType(int.class)
508                 .checkGetParameterizedType("int");
509     }
510 
testEnumConstructor_withMetadata()511     public void testEnumConstructor_withMetadata() throws Exception {
512         Class<?> clazz = loadTestInnerClassWithMetadata("TestEnum");
513         Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, int.class);
514 
515         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
516         helper.checkStandardParametersBehavior()
517                 // The extra spaces below are the result of a trivial upstream bug in
518                 // Parameter.toString() due to Modifier.toString(int) outputting nothing for
519                 // "SYNTHETIC".
520                 .checkParametersToString("[ java.lang.String $enum$name,  int $enum$ordinal]")
521                 .checkParametersNoVarArgs();
522 
523         helper.getParameterTestHelper(0)
524                 .checkName(true /* expectedNameIsPresent */, "$enum$name")
525                 .checkModifiers(4096) // 4096 == Modifier.SYNTHETIC
526                 .checkImplicitAndSynthetic(false, true)
527                 .checkGetType(String.class)
528                 .checkGetParameterizedType("class java.lang.String");
529 
530         helper.getParameterTestHelper(1)
531                 .checkName(true /* expectedNameIsPresent */, "$enum$ordinal")
532                 .checkModifiers(4096) // 4096 == Modifier.SYNTHETIC
533                 .checkImplicitAndSynthetic(false, true)
534                 .checkGetType(int.class)
535                 .checkGetParameterizedType("int");
536     }
537 
testEnumValueOf()538     public void testEnumValueOf() throws Exception {
539         Method method = TestEnum.class.getDeclaredMethod("valueOf", String.class);
540 
541         ExecutableTestHelper helper = new ExecutableTestHelper(method);
542         helper.checkStandardParametersBehavior()
543                 .checkParametersToString("[java.lang.String arg0]")
544                 .checkParametersMetadataNotAvailable()
545                 .checkParametersNoVarArgs();
546 
547         helper.getParameterTestHelper(0)
548                 .checkGetType(String.class)
549                 .checkGetParameterizedType("class java.lang.String");
550     }
551 
testEnumValueOf_withMetadata()552     public void testEnumValueOf_withMetadata() throws Exception {
553         Class<?> clazz = loadTestInnerClassWithMetadata("TestEnum");
554         Method method = clazz.getDeclaredMethod("valueOf", String.class);
555 
556         ExecutableTestHelper helper = new ExecutableTestHelper(method);
557         helper.checkStandardParametersBehavior()
558                 // The extra space below are the result of a trivial upstream bug in
559                 // Parameter.toString() due to Modifier.toString(int) outputting nothing for
560                 // "MANDATED".
561                 .checkParametersToString("[ java.lang.String name]")
562                 .checkParametersNoVarArgs();
563 
564         helper.getParameterTestHelper(0)
565                 .checkName(true /* expectedNameIsPresent */, "name")
566                 .checkModifiers(32768) // 32768 == Modifier.MANDATED
567                 .checkImplicitAndSynthetic(true, false)
568                 .checkGetType(String.class)
569                 .checkGetParameterizedType("class java.lang.String");
570     }
571 
572     private static class SingleVarArgs {
573         @SuppressWarnings("unused")
SingleVarArgs(String... p0)574         SingleVarArgs(String... p0) {}
575 
576         @SuppressWarnings("unused")
varArgs(String... p0)577         void varArgs(String... p0) {}
578     }
579 
testSingleVarArgsConstructor()580     public void testSingleVarArgsConstructor() throws Exception {
581         Constructor<?> constructor = SingleVarArgs.class.getDeclaredConstructor(String[].class);
582         checkSingleVarArgsParameter(constructor);
583     }
584 
testSingleVarArgsMethod()585     public void testSingleVarArgsMethod() throws Exception {
586         Method method = SingleVarArgs.class.getDeclaredMethod("varArgs", String[].class);
587         checkSingleVarArgsParameter(method);
588     }
589 
checkSingleVarArgsParameter(Executable executable)590     private static void checkSingleVarArgsParameter(Executable executable) {
591         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
592         helper.checkStandardParametersBehavior()
593                 .checkParametersToString("[java.lang.String... arg0]")
594                 .checkParametersMetadataNotAvailable();
595 
596         helper.getParameterTestHelper(0)
597                 .checkGetType(String[].class)
598                 .checkIsVarArg(true)
599                 .checkGetParameterizedType("class [Ljava.lang.String;");
600     }
601 
testSingleVarArgsConstructor_withMetadata()602     public void testSingleVarArgsConstructor_withMetadata() throws Exception {
603         Class<?> clazz = loadTestInnerClassWithMetadata("SingleVarArgs");
604         Constructor<?> constructor = clazz.getDeclaredConstructor(String[].class);
605         checkSingleVarArgsParameter_withMetadata(constructor);
606     }
607 
testSingleVarArgsMethod_withMetadata()608     public void testSingleVarArgsMethod_withMetadata() throws Exception {
609         Class<?> clazz = loadTestInnerClassWithMetadata("SingleVarArgs");
610         Method method = clazz.getDeclaredMethod("varArgs", String[].class);
611         checkSingleVarArgsParameter_withMetadata(method);
612     }
613 
checkSingleVarArgsParameter_withMetadata(Executable executable)614     private static void checkSingleVarArgsParameter_withMetadata(Executable executable) {
615         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
616         helper.checkStandardParametersBehavior()
617                 .checkParametersToString("[java.lang.String... p0]");
618 
619         helper.getParameterTestHelper(0)
620                 .checkName(true /* expectedNameIsPresent */, "p0")
621                 .checkModifiers(0)
622                 .checkImplicitAndSynthetic(false, false)
623                 .checkGetType(String[].class)
624                 .checkIsVarArg(true)
625                 .checkGetParameterizedType("class [Ljava.lang.String;");
626     }
627 
628     private static class MixedVarArgs {
629         @SuppressWarnings("unused")
MixedVarArgs(Integer[] p0, String... p1)630         MixedVarArgs(Integer[] p0, String... p1) {}
631         @SuppressWarnings("unused")
both(Integer[] p0, String... p1)632         void both(Integer[] p0, String... p1) {}
633     }
634 
testMixedVarArgsConstructor()635     public void testMixedVarArgsConstructor() throws Exception {
636         Constructor<?> constructor =
637                 MixedVarArgs.class.getDeclaredConstructor(Integer[].class, String[].class);
638         checkMixedVarArgsParameter(constructor);
639     }
640 
testMixedVarArgsMethod()641     public void testMixedVarArgsMethod() throws Exception {
642         Method method = MixedVarArgs.class.getDeclaredMethod("both", Integer[].class, String[].class);
643         checkMixedVarArgsParameter(method);
644     }
645 
checkMixedVarArgsParameter(Executable executable)646     private static void checkMixedVarArgsParameter(Executable executable) {
647         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
648         helper.checkStandardParametersBehavior()
649                 .checkParametersToString("[java.lang.Integer[] arg0, java.lang.String... arg1]")
650                 .checkParametersMetadataNotAvailable();
651 
652         helper.getParameterTestHelper(0)
653                 .checkGetType(Integer[].class)
654                 .checkIsVarArg(false)
655                 .checkGetParameterizedType("class [Ljava.lang.Integer;");
656 
657         helper.getParameterTestHelper(1)
658                 .checkGetType(String[].class)
659                 .checkIsVarArg(true)
660                 .checkGetParameterizedType("class [Ljava.lang.String;");
661     }
662 
663     private static class NonVarArgs {
664         @SuppressWarnings("unused")
NonVarArgs(Integer[] p0)665         NonVarArgs(Integer[] p0) {}
666         @SuppressWarnings("unused")
notVarArgs(Integer[] p0)667         void notVarArgs(Integer[] p0) {}
668     }
669 
testNonVarsArgsConstructor()670     public void testNonVarsArgsConstructor() throws Exception {
671         Constructor<?> constructor = NonVarArgs.class.getDeclaredConstructor(Integer[].class);
672         checkNonVarsArgsParameter(constructor);
673     }
674 
testNonVarsArgsMethod()675     public void testNonVarsArgsMethod() throws Exception {
676         Method method = NonVarArgs.class.getDeclaredMethod("notVarArgs", Integer[].class);
677         checkNonVarsArgsParameter(method);
678     }
679 
checkNonVarsArgsParameter(Executable executable)680     private static void checkNonVarsArgsParameter(Executable executable) {
681         ExecutableTestHelper helper = new ExecutableTestHelper(executable);
682         helper.checkStandardParametersBehavior()
683                 .checkParametersToString("[java.lang.Integer[] arg0]")
684                 .checkParametersMetadataNotAvailable();
685 
686         helper.getParameterTestHelper(0)
687                 .checkGetType(Integer[].class)
688                 .checkIsVarArg(false)
689                 .checkGetParameterizedType("class [Ljava.lang.Integer;");
690     }
691 
testAnonymousClassConstructor()692     public void testAnonymousClassConstructor() throws Exception {
693         Class<?> outerClass = ParameterTest.class;
694         Class<?> innerClass = getAnonymousClassWith1ParameterConstructor();
695         Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
696 
697         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
698         helper.checkStandardParametersBehavior()
699                 .checkParametersToString("[" + outerClass.getName() + " arg0]")
700                 .checkParametersMetadataNotAvailable()
701                 .checkParametersNoVarArgs();
702 
703         helper.getParameterTestHelper(0)
704                 .checkGetType(outerClass)
705                 .checkGetParameterizedType("class " + outerClass.getName() + "");
706     }
707 
getAnonymousClassWith1ParameterConstructor()708     private Class<?> getAnonymousClassWith1ParameterConstructor() {
709         // Deliberately not implemented with a lambda. Do not refactor.
710         Callable<String> anonymousClassObject = new Callable<String>() {
711             @Override
712             public String call() throws Exception {
713                 return ParameterTest.this.outerClassMethod();
714             }
715         };
716         return anonymousClassObject.getClass();
717     }
718 
testAnonymousClassConstructor_withMetadata()719     public void testAnonymousClassConstructor_withMetadata() throws Exception {
720         Class<?> outerClass = loadTestOuterClassWithMetadata();
721         Object outer = outerClass.newInstance();
722         Class<?> innerClass = (Class<?>) outerClass.getDeclaredMethod(
723                 "getAnonymousClassWith1ParameterConstructor").invoke(outer);
724         Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
725 
726         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
727         helper.checkStandardParametersBehavior()
728                 .checkParametersToString("[final " + outerClass.getName() + " this$0]")
729                 .checkParametersNoVarArgs();
730 
731         helper.getParameterTestHelper(0)
732                 .checkName(true /* expectedNameIsPresent */, "this$0")
733                 .checkModifiers(32784) // 32784 == Modifier.MANDATED & Modifier.FINAL
734                 .checkImplicitAndSynthetic(true, false)
735                 .checkGetType(outerClass)
736                 .checkGetParameterizedType("class " + outerClass.getName() + "");
737     }
738 
testMethodClassConstructor()739     public void testMethodClassConstructor() throws Exception {
740         Class<?> outerClass = ParameterTest.class;
741         Class<?> innerClass = getMethodClassWith1ImplicitParameterConstructor();
742         Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
743 
744         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
745         helper.checkStandardParametersBehavior()
746                 .checkParametersToString("[" + outerClass.getName() + " arg0]")
747                 .checkParametersMetadataNotAvailable()
748                 .checkParametersNoVarArgs();
749 
750         helper.getParameterTestHelper(0)
751                 .checkGetType(outerClass)
752                 .checkGetParameterizedType("class " + outerClass.getName() + "");
753     }
754 
getMethodClassWith1ImplicitParameterConstructor()755     private Class<?> getMethodClassWith1ImplicitParameterConstructor() {
756         class MethodClass {
757             MethodClass() {
758                 ParameterTest.this.outerClassMethod();
759             }
760         }
761         return MethodClass.class;
762     }
763 
testMethodClassConstructor_withMetadata()764     public void testMethodClassConstructor_withMetadata() throws Exception {
765         Class<?> outerClass = loadTestOuterClassWithMetadata();
766         Object outer = outerClass.newInstance();
767         Class<?> innerClass = (Class<?>) outerClass.getDeclaredMethod(
768                 "getMethodClassWith1ImplicitParameterConstructor").invoke(outer);
769         Constructor<?> constructor = innerClass.getDeclaredConstructor(outerClass);
770 
771         ExecutableTestHelper helper = new ExecutableTestHelper(constructor);
772         helper.checkStandardParametersBehavior()
773                 .checkParametersToString("[final " + outerClass.getName() + " this$0]")
774                 .checkParametersNoVarArgs();
775 
776         helper.getParameterTestHelper(0)
777                 .checkName(true /* expectedNameIsPresent */, "this$0")
778                 .checkModifiers(32784) // 32784 == Modifier.MANDATED & Modifier.FINAL
779                 .checkImplicitAndSynthetic(true, false)
780                 .checkGetType(outerClass)
781                 .checkGetParameterizedType("class " + outerClass.getName() + "");
782     }
783 
784     private static class NonIdenticalParameters {
785         @SuppressWarnings("unused")
method0(String p0)786         void method0(String p0) {}
787         @SuppressWarnings("unused")
method1(String p0)788         void method1(String p0) {}
789     }
790 
testEquals_checksExecutable()791     public void testEquals_checksExecutable() throws Exception {
792         Method method0 = NonIdenticalParameters.class.getDeclaredMethod("method0", String.class);
793         Method method1 = NonIdenticalParameters.class.getDeclaredMethod("method1", String.class);
794         Parameter method0P0 = method0.getParameters()[0];
795         Parameter method1P0 = method1.getParameters()[0];
796         assertFalse(method0P0.equals(method1P0));
797         assertFalse(method1P0.equals(method0P0));
798         assertTrue(method0P0.equals(method0P0));
799     }
800 
testManyParameters_withMetadata()801     public void testManyParameters_withMetadata() throws Exception {
802         int expectedParameterCount = 300;
803         Class<?>[] parameterTypes = new Class[expectedParameterCount];
804         Arrays.fill(parameterTypes, int.class);
805         Method method = getMetadataVariationsMethod("manyParameters", parameterTypes);
806         Parameter[] parameters = method.getParameters();
807         assertEquals(expectedParameterCount, parameters.length);
808 
809         NumberFormat format = NumberFormat.getIntegerInstance();
810         format.setMinimumIntegerDigits(3);
811         for (int i = 0; i < parameters.length; i++) {
812             assertEquals(true, parameters[i].isNamePresent());
813             assertEquals(Modifier.FINAL, parameters[i].getModifiers());
814             assertEquals("a" + format.format(i), parameters[i].getName());
815         }
816     }
817 
testEmptyMethodParametersAnnotation_withMetadata()818     public void testEmptyMethodParametersAnnotation_withMetadata() throws Exception {
819         Method method = getMetadataVariationsMethod("emptyMethodParametersAnnotation");
820         assertEquals(0, method.getParameters().length);
821     }
822 
testTooManyAccessFlags_withMetadata()823     public void testTooManyAccessFlags_withMetadata() throws Exception {
824         Method method = getMetadataVariationsMethod("tooManyAccessFlags", String.class);
825         checkGetParametersThrowsMalformedParametersException(method);
826     }
827 
testTooFewAccessFlags_withMetadata()828     public void testTooFewAccessFlags_withMetadata() throws Exception {
829         Method method = getMetadataVariationsMethod(
830                 "tooFewAccessFlags", String.class, String.class);
831         checkGetParametersThrowsMalformedParametersException(method);
832     }
833 
testTooManyNames_withMetadata()834     public void testTooManyNames_withMetadata() throws Exception {
835         Method method = getMetadataVariationsMethod("tooManyNames", String.class);
836         checkGetParametersThrowsMalformedParametersException(method);
837     }
838 
testTooFewNames_withMetadata()839     public void testTooFewNames_withMetadata() throws Exception {
840         Method method = getMetadataVariationsMethod("tooFewNames", String.class, String.class);
841         checkGetParametersThrowsMalformedParametersException(method);
842     }
843 
testTooManyBoth_withMetadata()844     public void testTooManyBoth_withMetadata() throws Exception {
845         Method method = getMetadataVariationsMethod("tooManyBoth", String.class);
846         checkGetParametersThrowsMalformedParametersException(method);
847     }
848 
testTooFewBoth_withMetadata()849     public void testTooFewBoth_withMetadata() throws Exception {
850         Method method = getMetadataVariationsMethod("tooFewBoth", String.class, String.class);
851         checkGetParametersThrowsMalformedParametersException(method);
852     }
853 
testNullName_withMetadata()854     public void testNullName_withMetadata() throws Exception {
855         Method method = getMetadataVariationsMethod("nullName", String.class);
856         Parameter parameter0 = method.getParameters()[0];
857         assertEquals("arg0", parameter0.getName());
858         assertEquals(Modifier.FINAL, parameter0.getModifiers());
859     }
860 
testEmptyName_withMetadata()861     public void testEmptyName_withMetadata() throws Exception {
862         Method method = getMetadataVariationsMethod("emptyName", String.class);
863         checkGetParametersThrowsMalformedParametersException(method);
864     }
865 
testNameWithSemicolon_withMetadata()866     public void testNameWithSemicolon_withMetadata() throws Exception {
867         Method method = getMetadataVariationsMethod("nameWithSemicolon", String.class);
868         checkGetParametersThrowsMalformedParametersException(method);
869     }
870 
testNameWithSlash_withMetadata()871     public void testNameWithSlash_withMetadata() throws Exception {
872         Method method = getMetadataVariationsMethod("nameWithSlash", String.class);
873         checkGetParametersThrowsMalformedParametersException(method);
874     }
875 
testNameWithPeriod_withMetadata()876     public void testNameWithPeriod_withMetadata() throws Exception {
877         Method method = getMetadataVariationsMethod("nameWithPeriod", String.class);
878         checkGetParametersThrowsMalformedParametersException(method);
879     }
880 
testNameWithOpenSquareBracket_withMetadata()881     public void testNameWithOpenSquareBracket_withMetadata() throws Exception {
882         Method method = getMetadataVariationsMethod("nameWithOpenSquareBracket", String.class);
883         checkGetParametersThrowsMalformedParametersException(method);
884     }
885 
testBadAccessModifier_withMetadata()886     public void testBadAccessModifier_withMetadata() throws Exception {
887         Method method = getMetadataVariationsMethod("badAccessModifier", String.class);
888         checkGetParametersThrowsMalformedParametersException(method);
889     }
890 
testBadlyFormedAnnotation()891     public void testBadlyFormedAnnotation() throws Exception {
892         Method method = getMetadataVariationsMethod("badlyFormedAnnotation", String.class);
893         // Badly formed annotations are treated as if the annotation is entirely absent.
894         Parameter parameter0 = method.getParameters()[0];
895         assertFalse(parameter0.isNamePresent());
896     }
897 
898     /** A non-static method that exists to be called by inner classes, lambdas, etc. */
outerClassMethod()899     private String outerClassMethod() {
900         return "Howdy";
901     }
902 
903     private static class ExecutableTestHelper {
904         private final Executable executable;
905 
ExecutableTestHelper(Executable executable)906         ExecutableTestHelper(Executable executable) {
907             this.executable = executable;
908         }
909 
910         @DependsOnParameterMetadata
checkParametersToString(String expectedString)911         ExecutableTestHelper checkParametersToString(String expectedString) {
912             assertEquals(expectedString, Arrays.toString(executable.getParameters()));
913             return this;
914         }
915 
916         /**
917          * Combines checks that should be true of any result from
918          * {@link Executable#getParameters()}
919          */
checkStandardParametersBehavior()920         ExecutableTestHelper checkStandardParametersBehavior() {
921             return checkGetParametersClonesArray()
922                     .checkParametersGetDeclaringExecutable()
923                     .checkParametersEquals()
924                     .checkParametersHashcode();
925         }
926 
checkParametersGetDeclaringExecutable()927         ExecutableTestHelper checkParametersGetDeclaringExecutable() {
928             for (Parameter p : executable.getParameters()) {
929                 assertSame(executable, p.getDeclaringExecutable());
930             }
931             return this;
932         }
933 
checkGetParametersClonesArray()934         ExecutableTestHelper checkGetParametersClonesArray() {
935             Parameter[] parameters1 = executable.getParameters();
936             Parameter[] parameters2 = executable.getParameters();
937             assertNotSame(parameters1, parameters2);
938 
939             assertEquals(parameters1.length, parameters2.length);
940             for (int i = 0; i < parameters1.length; i++) {
941                 assertSame(parameters1[i], parameters2[i]);
942             }
943             return this;
944         }
945 
checkParametersEquals()946         ExecutableTestHelper checkParametersEquals() {
947             Parameter[] parameters = executable.getParameters();
948             for (int i = 0; i < parameters.length; i++) {
949                 assertEquals(parameters[i], parameters[i]);
950                 if (i > 0) {
951                     assertFalse(parameters[0].equals(parameters[i]));
952                     assertFalse(parameters[i].equals(parameters[0]));
953                 }
954             }
955             return this;
956         }
957 
checkParametersHashcode()958         ExecutableTestHelper checkParametersHashcode() {
959             for (Parameter parameter : executable.getParameters()) {
960                 // Not much to assert. Just call the method and check it is consistent.
961                 assertEquals(parameter.hashCode(), parameter.hashCode());
962             }
963             return this;
964         }
965 
966         @DependsOnParameterMetadata
checkParametersMetadataNotAvailable()967         ExecutableTestHelper checkParametersMetadataNotAvailable() {
968             ParameterTestHelper[] parameterTestHelpers = getParameterTestHelpers();
969             for (int i = 0; i < parameterTestHelpers.length; i++) {
970                 ParameterTestHelper parameterTestHelper = parameterTestHelpers[i];
971                 parameterTestHelper.checkName(false, "arg" + i)
972                         .checkImplicitAndSynthetic(false, false)
973                         .checkModifiers(0);
974             }
975             return this;
976         }
977 
978         /**
979          * Checks that non of the parameters return {@code true} for {@link Parameter#isVarArgs()}.
980          */
checkParametersNoVarArgs()981         ExecutableTestHelper checkParametersNoVarArgs() {
982             for (ParameterTestHelper parameterTestHelper : getParameterTestHelpers()) {
983                 parameterTestHelper.checkIsVarArg(false);
984             }
985             return this;
986         }
987 
getParameterTestHelper(int index)988         ParameterTestHelper getParameterTestHelper(int index) {
989             return new ParameterTestHelper(executable.getParameters()[index]);
990         }
991 
getParameterTestHelpers()992         private ParameterTestHelper[] getParameterTestHelpers() {
993             final int parameterCount = executable.getParameterCount();
994             ParameterTestHelper[] parameterTestHelpers = new ParameterTestHelper[parameterCount];
995             for (int i = 0; i < parameterCount; i++) {
996                 parameterTestHelpers[i] = getParameterTestHelper(i);
997             }
998             return parameterTestHelpers;
999         }
1000 
1001         private static class ParameterTestHelper {
1002             private final Parameter parameter;
1003 
ParameterTestHelper(Parameter parameter)1004             ParameterTestHelper(Parameter parameter) {
1005                 this.parameter = parameter;
1006             }
1007 
checkGetType(Class<?> expectedType)1008             ParameterTestHelper checkGetType(Class<?> expectedType) {
1009                 assertEquals(expectedType, parameter.getType());
1010                 return this;
1011             }
1012 
1013             @DependsOnParameterMetadata
checkName(boolean expectedIsNamePresent, String expectedName)1014             ParameterTestHelper checkName(boolean expectedIsNamePresent, String expectedName) {
1015                 assertEquals(expectedIsNamePresent, parameter.isNamePresent());
1016                 assertEquals(expectedName, parameter.getName());
1017                 return this;
1018             }
1019 
1020             @DependsOnParameterMetadata
checkModifiers(int expectedModifiers)1021             ParameterTestHelper checkModifiers(int expectedModifiers) {
1022                 assertEquals(expectedModifiers, parameter.getModifiers());
1023                 return this;
1024             }
1025 
checkGetParameterizedType(String expectedParameterizedTypeString)1026             ParameterTestHelper checkGetParameterizedType(String expectedParameterizedTypeString) {
1027                 assertEquals(
1028                         expectedParameterizedTypeString,
1029                         parameter.getParameterizedType().toString());
1030                 return this;
1031             }
1032 
1033             @DependsOnParameterMetadata
checkImplicitAndSynthetic( boolean expectedIsImplicit, boolean expectedIsSynthetic)1034             ParameterTestHelper checkImplicitAndSynthetic(
1035                     boolean expectedIsImplicit, boolean expectedIsSynthetic) {
1036                 assertEquals(expectedIsImplicit, parameter.isImplicit());
1037                 assertEquals(expectedIsSynthetic, parameter.isSynthetic());
1038                 return this;
1039             }
1040 
checkIsVarArg(boolean expectedIsVarArg)1041             ParameterTestHelper checkIsVarArg(boolean expectedIsVarArg) {
1042                 assertEquals(expectedIsVarArg, parameter.isVarArgs());
1043                 return this;
1044             }
1045         }
1046     }
1047 
createClassLoaderForDexResource(File dexDir, String resourceName)1048     private static ClassLoader createClassLoaderForDexResource(File dexDir, String resourceName)
1049             throws Exception {
1050         File dexFile = new File(dexDir, resourceName);
1051         copyResource(resourceName, dexFile);
1052         return new PathClassLoader(dexFile.getAbsolutePath(), ClassLoader.getSystemClassLoader());
1053     }
1054 
1055     /**
1056      * Copy a resource in the libcore/java/lang/reflect/parameter/ resource path to the indicated
1057      * target file.
1058      */
copyResource(String resourceName, File destination)1059     private static void copyResource(String resourceName, File destination) throws Exception {
1060         assertFalse(destination.exists());
1061         ClassLoader classLoader = ParameterTest.class.getClassLoader();
1062         assertNotNull(classLoader);
1063 
1064         final String RESOURCE_PATH = "libcore/java/lang/reflect/parameter/";
1065         String fullResourcePath = RESOURCE_PATH + resourceName;
1066         try (InputStream in = classLoader.getResourceAsStream(fullResourcePath);
1067              FileOutputStream out = new FileOutputStream(destination)) {
1068             if (in == null) {
1069                 throw new IllegalStateException("Resource not found: " + fullResourcePath);
1070             }
1071             Streams.copy(in, out);
1072         }
1073     }
1074 
1075     /**
1076      * Loads an inner class from the ParameterMetadataTestClasses class defined in a separate dex
1077      * file. See src/test/java/libcore/java/lang/reflect/parameter/ for the associated source code.
1078      */
loadTestInnerClassWithMetadata(String name)1079     private Class<?> loadTestInnerClassWithMetadata(String name) throws Exception {
1080         return classesWithMetadataClassLoader.loadClass(
1081                 "libcore.java.lang.reflect.parameter.ParameterMetadataTestClasses$" + name);
1082     }
1083 
1084     /**
1085      * Loads the ParameterMetadataTestClasses class defined in a separate dex file.
1086      * See src/test/java/libcore/java/lang/reflect/parameter/ for the associated source code.
1087      */
loadTestOuterClassWithMetadata()1088     private Class<?> loadTestOuterClassWithMetadata() throws Exception {
1089         return classesWithMetadataClassLoader.loadClass(
1090                 "libcore.java.lang.reflect.parameter.ParameterMetadataTestClasses");
1091     }
1092 
1093     /**
1094      * Loads a method from the MetadataVariations class defined in a separate dex file. See
1095      * src/test/java/libcore/java/lang/reflect/parameter/ for the associated source code.
1096      */
getMetadataVariationsMethod(String methodName, Class<?>... parameterTypes)1097     private Method getMetadataVariationsMethod(String methodName, Class<?>... parameterTypes)
1098             throws Exception {
1099         Class<?> metadataVariationsClass = metadataVariationsClassLoader.loadClass(
1100                 "libcore.java.lang.reflect.parameter.MetadataVariations");
1101         return metadataVariationsClass.getDeclaredMethod(methodName, parameterTypes);
1102     }
1103 
checkGetParametersThrowsMalformedParametersException(Method method)1104     private static void checkGetParametersThrowsMalformedParametersException(Method method) {
1105         try {
1106             method.getParameters();
1107             fail();
1108         } catch (MalformedParametersException expected) {}
1109     }
1110 }
1111