1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package tests.api.java.lang.reflect;
19
20import dalvik.annotation.TestLevel;
21import dalvik.annotation.TestTargetNew;
22import dalvik.annotation.TestTargetClass;
23
24import java.lang.annotation.Annotation;
25import java.lang.annotation.ElementType;
26import java.lang.annotation.Retention;
27import java.lang.annotation.RetentionPolicy;
28import java.lang.annotation.Target;
29import java.lang.reflect.Constructor;
30import java.lang.reflect.Modifier;
31import java.lang.reflect.Type;
32import java.lang.reflect.TypeVariable;
33import java.util.Arrays;
34import java.util.HashSet;
35import java.util.Set;
36
37@TestTargetClass(
38        value = Constructor.class,
39        untestedMethods = {
40            @TestTargetNew(
41               level = TestLevel.NOT_FEASIBLE,
42               method = "isSynthetic",
43               args = {},
44               notes =  "Since code which relies on synthetic members is not " +
45               "portable, this should not be tested"
46            )
47        })
48public class ConstructorTest extends junit.framework.TestCase {
49
50
51    @Retention(RetentionPolicy.RUNTIME)
52    @Target( {ElementType.CONSTRUCTOR, ElementType.PARAMETER})
53    static @interface ConstructorTestAnnotationRuntime0 {
54    }
55
56    @Retention(RetentionPolicy.RUNTIME)
57    @Target( {ElementType.CONSTRUCTOR, ElementType.PARAMETER})
58    static @interface ConstructorTestAnnotationRuntime1 {
59    }
60
61    @Retention(RetentionPolicy.CLASS)
62    @Target( {ElementType.CONSTRUCTOR, ElementType.PARAMETER})
63    static @interface ConstructorTestAnnotationClass0 {
64    }
65
66    @Retention(RetentionPolicy.SOURCE)
67    @Target( {ElementType.CONSTRUCTOR, ElementType.PARAMETER})
68    static @interface ConstructorTestAnnotationSource0 {
69    }
70
71    static class ConstructorTestHelper extends Object {
72        int cval;
73
74        @ConstructorTestAnnotationRuntime0
75        @ConstructorTestAnnotationRuntime1
76        @ConstructorTestAnnotationClass0
77        @ConstructorTestAnnotationSource0
78        public ConstructorTestHelper() throws IndexOutOfBoundsException {
79            cval = 99;
80        }
81
82        public ConstructorTestHelper(
83                @ConstructorTestAnnotationRuntime0
84                @ConstructorTestAnnotationRuntime1
85                @ConstructorTestAnnotationClass0
86                @ConstructorTestAnnotationSource0 Object x) {
87        }
88
89        public ConstructorTestHelper(String... x) {
90        }
91
92        private ConstructorTestHelper(int a) {
93        }
94
95        protected ConstructorTestHelper(long a) {
96        }
97
98        public int check() {
99            return cval;
100        }
101    }
102
103    static class GenericConstructorTestHelper<T, S extends T, E extends Exception> {
104        public GenericConstructorTestHelper(T t, S s) {}
105        public GenericConstructorTestHelper() throws E{}
106    }
107
108    static class NoPublicConstructorTestHelper {
109        // This class has no public constructor.
110    }
111
112//    Used to test synthetic constructor.
113//
114//    static class Outer {
115//        private Outer(){}
116//        class Inner {
117//            {new Outer();}
118//        }
119//    }
120
121    /**
122     * @tests java.lang.reflect.Constructor#getDeclaredAnnotations()
123     */
124    @TestTargetNew(
125        level = TestLevel.COMPLETE,
126        notes = "",
127        method = "getParameterAnnotations",
128        args = {}
129    )
130    public void test_getParameterAnnotations() throws Exception {
131        Constructor<ConstructorTestHelper> ctor1 = ConstructorTestHelper.class
132                .getConstructor(Object.class);
133        Annotation[][] paramAnnotations = ctor1.getParameterAnnotations();
134        assertEquals("Annotations for wrong number of parameters returned", 1,
135                paramAnnotations.length);
136        assertEquals("Wrong number of annotations returned", 2,
137                paramAnnotations[0].length);
138
139        Set<Class<?>> ignoreOrder = new HashSet<Class<?>>();
140        ignoreOrder.add(paramAnnotations[0][0].annotationType());
141        ignoreOrder.add(paramAnnotations[0][1].annotationType());
142
143        assertTrue("Missing ConstructorTestAnnotationRuntime0", ignoreOrder
144                .contains(ConstructorTestAnnotationRuntime0.class));
145        assertTrue("Missing ConstructorTestAnnotationRuntime1", ignoreOrder
146                .contains(ConstructorTestAnnotationRuntime1.class));
147    }
148
149
150    /**
151     * @tests java.lang.reflect.Constructor#getDeclaredAnnotations()
152     */
153    @TestTargetNew(
154        level = TestLevel.COMPLETE,
155        notes = "",
156        method = "getDeclaredAnnotations",
157        args = {}
158    )
159    public void test_getDeclaredAnnotations() throws Exception {
160        Constructor<ConstructorTestHelper> ctor1 = null;
161        ctor1 = ConstructorTestHelper.class.getConstructor(new Class[0]);
162        Annotation[] annotations = ctor1.getDeclaredAnnotations();
163        assertEquals("Wrong number of annotations returned", 2,
164                annotations.length);
165        Set<Class<?>> ignoreOrder = new HashSet<Class<?>>();
166        ignoreOrder.add(annotations[0].annotationType());
167        ignoreOrder.add(annotations[1].annotationType());
168
169        assertTrue("Missing ConstructorTestAnnotationRuntime0", ignoreOrder
170                .contains(ConstructorTestAnnotationRuntime0.class));
171        assertTrue("Missing ConstructorTestAnnotationRuntime1", ignoreOrder
172                .contains(ConstructorTestAnnotationRuntime1.class));
173    }
174
175    /**
176     * @tests java.lang.reflect.Constructor#isVarargs()
177     */
178    @TestTargetNew(
179        level = TestLevel.COMPLETE,
180        notes = "",
181        method = "isVarArgs",
182        args = {}
183    )
184    public void test_isVarArgs() throws Exception {
185        Constructor<ConstructorTestHelper> varArgCtor = ConstructorTestHelper.class
186                .getConstructor(String[].class);
187        assertTrue("Vararg constructor not recognized", varArgCtor.isVarArgs());
188
189        Constructor<ConstructorTestHelper> nonVarArgCtor = ConstructorTestHelper.class
190                .getConstructor(Object.class);
191        assertFalse("Non vararg constructor recognized as vararg constructor",
192                nonVarArgCtor.isVarArgs());
193    }
194
195    /**
196     * @tests java.lang.reflect.Constructor#hashCode()
197     */
198    @TestTargetNew(
199        level = TestLevel.COMPLETE,
200        notes = "",
201        method = "hashCode",
202        args = {}
203    )
204    public void test_hashCode() throws Exception {
205        Constructor<ConstructorTestHelper> constructor = ConstructorTestHelper.class
206                .getConstructor();
207        assertEquals(
208                "The constructor's hashCode is not equal to the hashCode of the name of the declaring class",
209                ConstructorTestHelper.class.getName().hashCode(), constructor
210                        .hashCode());
211    }
212
213    /**
214     * @tests java.lang.reflect.Constructor#toGenericString()
215     */
216    @SuppressWarnings("unchecked")
217    @TestTargetNew(
218        level = TestLevel.COMPLETE,
219        notes = "",
220        method = "toGenericString",
221        args = {}
222    )
223    public void test_toGenericString() throws Exception {
224        Constructor<GenericConstructorTestHelper> genericCtor = GenericConstructorTestHelper.class
225                .getConstructor(Object.class, Object.class);
226        assertEquals(
227                "Wrong generic string returned",
228                "public tests.api.java.lang.reflect.ConstructorTest$GenericConstructorTestHelper(T,S)",
229                genericCtor.toGenericString());
230        Constructor<GenericConstructorTestHelper> ctor = GenericConstructorTestHelper.class
231                .getConstructor();
232        assertEquals(
233                "Wrong generic string returned",
234                "public tests.api.java.lang.reflect.ConstructorTest$GenericConstructorTestHelper() throws E",
235                ctor.toGenericString());
236    }
237
238 /**
239     * @tests java.lang.reflect.Constructor#equals(java.lang.Object)
240     */
241    @TestTargetNew(
242        level = TestLevel.COMPLETE,
243        notes = "",
244        method = "equals",
245        args = {java.lang.Object.class}
246    )
247    public void test_equalsLjava_lang_Object() {
248        Constructor<ConstructorTestHelper> ctor1 = null, ctor2 = null;
249        try {
250            ctor1 = ConstructorTestHelper.class.getConstructor(
251                    new Class[0]);
252            ctor2 = ConstructorTestHelper.class.getConstructor(Object.class);
253        } catch (Exception e) {
254            fail("Exception during equals test : " + e.getMessage());
255        }
256        assertTrue("Different Contructors returned equal", !ctor1.equals(ctor2));
257    }
258
259    /**
260     * @tests java.lang.reflect.Constructor#getDeclaringClass()
261     */
262    @TestTargetNew(
263        level = TestLevel.COMPLETE,
264        notes = "",
265        method = "getDeclaringClass",
266        args = {}
267    )
268    public void test_getDeclaringClass() {
269        boolean val = false;
270        try {
271            Class<? extends ConstructorTestHelper> pclass = new ConstructorTestHelper().getClass();
272            Constructor<? extends ConstructorTestHelper> ctor = pclass.getConstructor(new Class[0]);
273            val = ctor.getDeclaringClass().equals(pclass);
274        } catch (Exception e) {
275            fail("Exception during test : " + e.getMessage());
276        }
277        assertTrue("Returned incorrect declaring class", val);
278    }
279
280    /**
281     * @tests java.lang.reflect.Constructor#getExceptionTypes()
282     */
283    @TestTargetNew(
284        level = TestLevel.COMPLETE,
285        notes = "",
286        method = "getExceptionTypes",
287        args = {}
288    )
289    public void test_getExceptionTypes() {
290        // Test for method java.lang.Class []
291        // java.lang.reflect.Constructor.getExceptionTypes()
292        Class[] exceptions = null;
293        Class<? extends IndexOutOfBoundsException> ex = null;
294        try {
295            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
296                    .getConstructor(new Class[0]);
297            exceptions = ctor.getExceptionTypes();
298            ex = new IndexOutOfBoundsException().getClass();
299        } catch (Exception e) {
300            fail("Exception during test : " + e.getMessage());
301        }
302        assertEquals("Returned exception list of incorrect length",
303                1, exceptions.length);
304        assertTrue("Returned incorrect exception", exceptions[0].equals(ex));
305    }
306
307    /**
308     * @tests java.lang.reflect.Constructor#getModifiers()
309     */
310    @TestTargetNew(
311        level = TestLevel.COMPLETE,
312        notes = "",
313        method = "getModifiers",
314        args = {}
315    )
316    public void test_getModifiers() {
317        // Test for method int java.lang.reflect.Constructor.getModifiers()
318        int mod = 0;
319        try {
320            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
321                    .getConstructor(new Class[0]);
322            mod = ctor.getModifiers();
323            assertTrue("Returned incorrect modifers for public ctor",
324                    ((mod & Modifier.PUBLIC) == Modifier.PUBLIC)
325                            && ((mod & Modifier.PRIVATE) == 0));
326        } catch (NoSuchMethodException e) {
327            fail("Exception during test : " + e.getMessage());
328        }
329        try {
330            Class[] cl = { int.class };
331            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
332                    .getDeclaredConstructor(cl);
333            mod = ctor.getModifiers();
334            assertTrue("Returned incorrect modifers for private ctor",
335                    ((mod & Modifier.PRIVATE) == Modifier.PRIVATE)
336                            && ((mod & Modifier.PUBLIC) == 0));
337        } catch (NoSuchMethodException e) {
338            fail("Exception during test : " + e.getMessage());
339        }
340        try {
341            Class[] cl = { long.class };
342            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
343                    .getDeclaredConstructor(cl);
344            mod = ctor.getModifiers();
345            assertTrue("Returned incorrect modifers for private ctor",
346                    ((mod & Modifier.PROTECTED) == Modifier.PROTECTED)
347                            && ((mod & Modifier.PUBLIC) == 0));
348        } catch (NoSuchMethodException e) {
349            fail("NoSuchMethodException during test : " + e.getMessage());
350        }
351    }
352
353    /**
354     * @tests java.lang.reflect.Constructor#getName()
355     */
356    @TestTargetNew(
357        level = TestLevel.COMPLETE,
358        notes = "",
359        method = "getName",
360        args = {}
361    )
362    public void test_getName() {
363        // Test for method java.lang.String
364        // java.lang.reflect.Constructor.getName()
365        try {
366            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
367                    .getConstructor(new Class[0]);
368            assertTrue(
369                    "Returned incorrect name: " + ctor.getName(),
370                    ctor
371                            .getName()
372                            .equals(
373                                    "tests.api.java.lang.reflect.ConstructorTest$ConstructorTestHelper"));
374        } catch (Exception e) {
375            fail("Exception obtaining contructor : " + e.getMessage());
376        }
377    }
378
379    /**
380     * @tests java.lang.reflect.Constructor#getParameterTypes()
381     */
382    @TestTargetNew(
383        level = TestLevel.COMPLETE,
384        notes = "",
385        method = "getParameterTypes",
386        args = {}
387    )
388    public void test_getParameterTypes() {
389        // Test for method java.lang.Class []
390        // java.lang.reflect.Constructor.getParameterTypes()
391        Class[] types = null;
392        try {
393            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
394                    .getConstructor(new Class[0]);
395            types = ctor.getParameterTypes();
396        } catch (Exception e) {
397            fail("Exception during getParameterTypes test:"
398                    + e.toString());
399        }
400        assertEquals("Incorrect parameter returned", 0, types.length);
401
402        Class[] parms = null;
403        try {
404            parms = new Class[1];
405            parms[0] = new Object().getClass();
406            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
407                    .getConstructor(parms);
408            types = ctor.getParameterTypes();
409        } catch (Exception e) {
410            fail("Exception during getParameterTypes test:"
411                    + e.toString());
412        }
413        assertTrue("Incorrect parameter returned", types[0].equals(parms[0]));
414    }
415
416    /**
417     * @tests java.lang.reflect.Constructor#getGenericParameterTypes()
418     */
419    @TestTargetNew(
420        level = TestLevel.COMPLETE,
421        notes = "",
422        method = "getGenericParameterTypes",
423        args = {}
424    )
425    @SuppressWarnings("unchecked")
426    public void test_getGenericParameterTypes() {
427        Type[] types = null;
428        try {
429            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper()
430                    .getClass().getConstructor(new Class[0]);
431            types = ctor.getGenericParameterTypes();
432        } catch (Exception e) {
433            fail("Exception during getParameterTypes test:" + e.toString());
434        }
435        assertEquals("Incorrect parameter returned", 0, types.length);
436
437        Class<?>[] parms = null;
438        try {
439            parms = new Class[] {Object.class};
440            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper()
441                    .getClass().getConstructor(parms);
442            types = ctor.getGenericParameterTypes();
443        } catch (Exception e) {
444            fail("Exception during getParameterTypes test:" + e.toString());
445        }
446        assertTrue("Incorrect parameter returned", types[0].equals(parms[0]));
447
448
449        try {
450            Constructor<GenericConstructorTestHelper> constructor = GenericConstructorTestHelper.class
451                    .getConstructor(Object.class, Object.class);
452            types = constructor.getGenericParameterTypes();
453        } catch (Exception e) {
454            fail("Exception during getParameterTypes test:" + e.toString());
455        }
456
457        assertEquals("Wrong number of parameter types returned", 2,
458                types.length);
459
460        assertEquals("Wrong number of parameter types returned", "T",
461                ((TypeVariable)types[0]).getName());
462        assertEquals("Wrong number of parameter types returned", "S",
463                ((TypeVariable)types[1]).getName());
464    }
465
466    /**
467     * @tests java.lang.reflect.Constructor#getGenericParameterTypes()
468     */
469    @TestTargetNew(
470        level = TestLevel.COMPLETE,
471        notes = "",
472        method = "getGenericExceptionTypes",
473        args = {}
474    )
475    @SuppressWarnings("unchecked")
476    public void test_getGenericExceptionTypes() {
477        Type[] types = null;
478
479        try {
480            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper()
481                    .getClass().getConstructor(new Class[0]);
482            types = ctor.getGenericExceptionTypes();
483        } catch (Exception e) {
484            fail("Exception during getGenericExceptionTypes test:" + e.toString());
485        }
486        assertEquals("Wrong number of exception types returned", 1, types.length);
487
488
489        try {
490            Constructor<GenericConstructorTestHelper> constructor = GenericConstructorTestHelper.class
491                    .getConstructor();
492            types = constructor.getGenericExceptionTypes();
493        } catch (Exception e) {
494            fail("Exception during getGenericExceptionTypes test:"
495                    + e.toString());
496        }
497
498        assertEquals("Wrong number of exception types returned", 1,
499                types.length);
500
501        assertEquals("Wrong exception name returned.", "E",
502                ((TypeVariable)types[0]).getName());
503
504    }
505
506
507
508    /**
509     * @tests java.lang.reflect.Constructor#newInstance(java.lang.Object[])
510     */
511    @TestTargetNew(
512        level = TestLevel.COMPLETE,
513        notes = "",
514        method = "newInstance",
515        args = {java.lang.Object[].class}
516    )
517    public void test_newInstance$Ljava_lang_Object() {
518        // Test for method java.lang.Object
519        // java.lang.reflect.Constructor.newInstance(java.lang.Object [])
520
521        ConstructorTestHelper test = null;
522        try {
523            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
524                    .getConstructor(new Class[0]);
525            test = ctor.newInstance((Object[])null);
526        } catch (Exception e) {
527            fail("Failed to create instance : " + e.getMessage());
528        }
529        assertEquals("improper instance created", 99, test.check());
530    }
531
532    /**
533     * @tests java.lang.reflect.Constructor#toString()
534     */
535    @TestTargetNew(
536        level = TestLevel.COMPLETE,
537        notes = "",
538        method = "toString",
539        args = {}
540    )
541    public void test_toString() {
542        // Test for method java.lang.String
543        // java.lang.reflect.Constructor.toString()
544        Class[] parms = null;
545        Constructor<? extends ConstructorTestHelper> ctor = null;
546        try {
547            parms = new Class[1];
548            parms[0] = new Object().getClass();
549            ctor = new ConstructorTestHelper().getClass().getConstructor(parms);
550        } catch (Exception e) {
551            fail("Exception during getParameterTypes test:"
552                    + e.toString());
553        }
554        assertTrue(
555                "Returned incorrect string representation: " + ctor.toString(),
556                ctor
557                        .toString()
558                        .equals(
559                                "public tests.api.java.lang.reflect.ConstructorTest$ConstructorTestHelper(java.lang.Object)"));
560    }
561
562    /**
563     * @tests java.lang.reflect.Constructor#getConstructor((Class[]) null)
564     */
565    @TestTargetNew(
566        level = TestLevel.COMPLETE,
567        notes = "",
568        method = "getConstructor",
569        args = {}
570    )
571    public void test_getConstructor() throws Exception {
572        // Passing new Class[0] should be equivalent to (Class[]) null.
573        Class<ConstructorTestHelper> c2 = ConstructorTestHelper.class;
574        assertEquals(c2.getConstructor(new Class[0]), c2.getConstructor((Class[]) null));
575        assertEquals(c2.getDeclaredConstructor(new Class[0]),
576                     c2.getDeclaredConstructor((Class[]) null));
577
578        // We can get a non-public constructor via getDeclaredConstructor...
579        Class<NoPublicConstructorTestHelper> c1 = NoPublicConstructorTestHelper.class;
580        c1.getDeclaredConstructor((Class[]) null);
581        // ...but not with getConstructor (which only returns public constructors).
582        try {
583            c1.getConstructor((Class[]) null);
584            fail("Should throw NoSuchMethodException");
585        } catch (NoSuchMethodException ex) {
586            // Expected.
587        }
588    }
589
590    /**
591     * Sets up the fixture, for example, open a network connection. This method
592     * is called before a test is executed.
593     */
594    protected void setUp() {
595    }
596
597    /**
598     * Tears down the fixture, for example, close a network connection. This
599     * method is called after a test is executed.
600     */
601    protected void tearDown() {
602    }
603}
604