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