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 java.lang.annotation.Annotation;
21import java.lang.annotation.ElementType;
22import java.lang.annotation.Retention;
23import java.lang.annotation.RetentionPolicy;
24import java.lang.annotation.Target;
25import java.lang.reflect.Constructor;
26import java.lang.reflect.Modifier;
27import java.lang.reflect.Type;
28import java.lang.reflect.TypeVariable;
29import java.util.Arrays;
30import java.util.HashSet;
31import java.util.Set;
32
33public class ConstructorTest extends junit.framework.TestCase {
34
35
36    @Retention(RetentionPolicy.RUNTIME)
37    @Target( {ElementType.CONSTRUCTOR, ElementType.PARAMETER})
38    static @interface ConstructorTestAnnotationRuntime0 {
39    }
40
41    @Retention(RetentionPolicy.RUNTIME)
42    @Target( {ElementType.CONSTRUCTOR, ElementType.PARAMETER})
43    static @interface ConstructorTestAnnotationRuntime1 {
44    }
45
46    @Retention(RetentionPolicy.CLASS)
47    @Target( {ElementType.CONSTRUCTOR, ElementType.PARAMETER})
48    static @interface ConstructorTestAnnotationClass0 {
49    }
50
51    @Retention(RetentionPolicy.SOURCE)
52    @Target( {ElementType.CONSTRUCTOR, ElementType.PARAMETER})
53    static @interface ConstructorTestAnnotationSource0 {
54    }
55
56    static class ConstructorTestHelper extends Object {
57        int cval;
58
59        @ConstructorTestAnnotationRuntime0
60        @ConstructorTestAnnotationRuntime1
61        @ConstructorTestAnnotationClass0
62        @ConstructorTestAnnotationSource0
63        public ConstructorTestHelper() throws IndexOutOfBoundsException {
64            cval = 99;
65        }
66
67        public ConstructorTestHelper(
68                @ConstructorTestAnnotationRuntime0
69                @ConstructorTestAnnotationRuntime1
70                @ConstructorTestAnnotationClass0
71                @ConstructorTestAnnotationSource0 Object x) {
72        }
73
74        public ConstructorTestHelper(String... x) {
75        }
76
77        private ConstructorTestHelper(int a) {
78        }
79
80        protected ConstructorTestHelper(long a) {
81        }
82
83        public int check() {
84            return cval;
85        }
86    }
87
88    static class GenericConstructorTestHelper<T, S extends T, E extends Exception> {
89        public GenericConstructorTestHelper(T t, S s) {}
90        public GenericConstructorTestHelper() throws E{}
91    }
92
93    static class NoPublicConstructorTestHelper {
94        // This class has no public constructor.
95    }
96
97//    Used to test synthetic constructor.
98//
99//    static class Outer {
100//        private Outer(){}
101//        class Inner {
102//            {new Outer();}
103//        }
104//    }
105
106    public void test_getParameterAnnotations() throws Exception {
107        Constructor<ConstructorTestHelper> ctor1 = ConstructorTestHelper.class
108                .getConstructor(Object.class);
109        Annotation[][] paramAnnotations = ctor1.getParameterAnnotations();
110        assertEquals("Annotations for wrong number of parameters returned", 1,
111                paramAnnotations.length);
112        assertEquals("Wrong number of annotations returned", 2,
113                paramAnnotations[0].length);
114
115        Set<Class<?>> ignoreOrder = new HashSet<Class<?>>();
116        ignoreOrder.add(paramAnnotations[0][0].annotationType());
117        ignoreOrder.add(paramAnnotations[0][1].annotationType());
118
119        assertTrue("Missing ConstructorTestAnnotationRuntime0", ignoreOrder
120                .contains(ConstructorTestAnnotationRuntime0.class));
121        assertTrue("Missing ConstructorTestAnnotationRuntime1", ignoreOrder
122                .contains(ConstructorTestAnnotationRuntime1.class));
123    }
124
125
126    public void test_getDeclaredAnnotations() throws Exception {
127        Constructor<ConstructorTestHelper> ctor1 = null;
128        ctor1 = ConstructorTestHelper.class.getConstructor(new Class[0]);
129        Annotation[] annotations = ctor1.getDeclaredAnnotations();
130        assertEquals("Wrong number of annotations returned", 2,
131                annotations.length);
132        Set<Class<?>> ignoreOrder = new HashSet<Class<?>>();
133        ignoreOrder.add(annotations[0].annotationType());
134        ignoreOrder.add(annotations[1].annotationType());
135
136        assertTrue("Missing ConstructorTestAnnotationRuntime0", ignoreOrder
137                .contains(ConstructorTestAnnotationRuntime0.class));
138        assertTrue("Missing ConstructorTestAnnotationRuntime1", ignoreOrder
139                .contains(ConstructorTestAnnotationRuntime1.class));
140    }
141
142    public void test_isVarArgs() throws Exception {
143        Constructor<ConstructorTestHelper> varArgCtor = ConstructorTestHelper.class
144                .getConstructor(String[].class);
145        assertTrue("Vararg constructor not recognized", varArgCtor.isVarArgs());
146
147        Constructor<ConstructorTestHelper> nonVarArgCtor = ConstructorTestHelper.class
148                .getConstructor(Object.class);
149        assertFalse("Non vararg constructor recognized as vararg constructor",
150                nonVarArgCtor.isVarArgs());
151    }
152
153    public void test_hashCode() throws Exception {
154        Constructor<ConstructorTestHelper> constructor = ConstructorTestHelper.class
155                .getConstructor();
156        assertEquals(
157                "The constructor's hashCode is not equal to the hashCode of the name of the declaring class",
158                ConstructorTestHelper.class.getName().hashCode(), constructor
159                        .hashCode());
160    }
161
162    @SuppressWarnings("unchecked")
163    public void test_toGenericString() throws Exception {
164        Constructor<GenericConstructorTestHelper> genericCtor = GenericConstructorTestHelper.class
165                .getConstructor(Object.class, Object.class);
166        assertEquals(
167                "Wrong generic string returned",
168                "public tests.api.java.lang.reflect.ConstructorTest$GenericConstructorTestHelper(T,S)",
169                genericCtor.toGenericString());
170        Constructor<GenericConstructorTestHelper> ctor = GenericConstructorTestHelper.class
171                .getConstructor();
172        assertEquals(
173                "Wrong generic string returned",
174                "public tests.api.java.lang.reflect.ConstructorTest$GenericConstructorTestHelper() throws E",
175                ctor.toGenericString());
176    }
177
178    public void test_equalsLjava_lang_Object() {
179        Constructor<ConstructorTestHelper> ctor1 = null, ctor2 = null;
180        try {
181            ctor1 = ConstructorTestHelper.class.getConstructor(
182                    new Class[0]);
183            ctor2 = ConstructorTestHelper.class.getConstructor(Object.class);
184        } catch (Exception e) {
185            fail("Exception during equals test : " + e.getMessage());
186        }
187        assertTrue("Different Contructors returned equal", !ctor1.equals(ctor2));
188    }
189
190    public void test_getDeclaringClass() {
191        boolean val = false;
192        try {
193            Class<? extends ConstructorTestHelper> pclass = new ConstructorTestHelper().getClass();
194            Constructor<? extends ConstructorTestHelper> ctor = pclass.getConstructor(new Class[0]);
195            val = ctor.getDeclaringClass().equals(pclass);
196        } catch (Exception e) {
197            fail("Exception during test : " + e.getMessage());
198        }
199        assertTrue("Returned incorrect declaring class", val);
200    }
201
202    public void test_getExceptionTypes() {
203        // Test for method java.lang.Class []
204        // java.lang.reflect.Constructor.getExceptionTypes()
205        Class[] exceptions = null;
206        Class<? extends IndexOutOfBoundsException> ex = null;
207        try {
208            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
209                    .getConstructor(new Class[0]);
210            exceptions = ctor.getExceptionTypes();
211            ex = new IndexOutOfBoundsException().getClass();
212        } catch (Exception e) {
213            fail("Exception during test : " + e.getMessage());
214        }
215        assertEquals("Returned exception list of incorrect length",
216                1, exceptions.length);
217        assertTrue("Returned incorrect exception", exceptions[0].equals(ex));
218    }
219
220    public void test_getModifiers() {
221        // Test for method int java.lang.reflect.Constructor.getModifiers()
222        int mod = 0;
223        try {
224            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
225                    .getConstructor(new Class[0]);
226            mod = ctor.getModifiers();
227            assertTrue("Returned incorrect modifers for public ctor",
228                    ((mod & Modifier.PUBLIC) == Modifier.PUBLIC)
229                            && ((mod & Modifier.PRIVATE) == 0));
230        } catch (NoSuchMethodException e) {
231            fail("Exception during test : " + e.getMessage());
232        }
233        try {
234            Class[] cl = { int.class };
235            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
236                    .getDeclaredConstructor(cl);
237            mod = ctor.getModifiers();
238            assertTrue("Returned incorrect modifers for private ctor",
239                    ((mod & Modifier.PRIVATE) == Modifier.PRIVATE)
240                            && ((mod & Modifier.PUBLIC) == 0));
241        } catch (NoSuchMethodException e) {
242            fail("Exception during test : " + e.getMessage());
243        }
244        try {
245            Class[] cl = { long.class };
246            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
247                    .getDeclaredConstructor(cl);
248            mod = ctor.getModifiers();
249            assertTrue("Returned incorrect modifers for private ctor",
250                    ((mod & Modifier.PROTECTED) == Modifier.PROTECTED)
251                            && ((mod & Modifier.PUBLIC) == 0));
252        } catch (NoSuchMethodException e) {
253            fail("NoSuchMethodException during test : " + e.getMessage());
254        }
255    }
256
257    public void test_getName() {
258        // Test for method java.lang.String
259        // java.lang.reflect.Constructor.getName()
260        try {
261            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
262                    .getConstructor(new Class[0]);
263            assertTrue(
264                    "Returned incorrect name: " + ctor.getName(),
265                    ctor
266                            .getName()
267                            .equals(
268                                    "tests.api.java.lang.reflect.ConstructorTest$ConstructorTestHelper"));
269        } catch (Exception e) {
270            fail("Exception obtaining contructor : " + e.getMessage());
271        }
272    }
273
274    public void test_getParameterTypes() {
275        // Test for method java.lang.Class []
276        // java.lang.reflect.Constructor.getParameterTypes()
277        Class[] types = null;
278        try {
279            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
280                    .getConstructor(new Class[0]);
281            types = ctor.getParameterTypes();
282        } catch (Exception e) {
283            fail("Exception during getParameterTypes test:"
284                    + e.toString());
285        }
286        assertEquals("Incorrect parameter returned", 0, types.length);
287
288        Class[] parms = null;
289        try {
290            parms = new Class[1];
291            parms[0] = new Object().getClass();
292            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
293                    .getConstructor(parms);
294            types = ctor.getParameterTypes();
295        } catch (Exception e) {
296            fail("Exception during getParameterTypes test:"
297                    + e.toString());
298        }
299        assertTrue("Incorrect parameter returned", types[0].equals(parms[0]));
300    }
301
302    @SuppressWarnings("unchecked")
303    public void test_getGenericParameterTypes() {
304        Type[] types = null;
305        try {
306            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper()
307                    .getClass().getConstructor(new Class[0]);
308            types = ctor.getGenericParameterTypes();
309        } catch (Exception e) {
310            fail("Exception during getParameterTypes test:" + e.toString());
311        }
312        assertEquals("Incorrect parameter returned", 0, types.length);
313
314        Class<?>[] parms = null;
315        try {
316            parms = new Class[] {Object.class};
317            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper()
318                    .getClass().getConstructor(parms);
319            types = ctor.getGenericParameterTypes();
320        } catch (Exception e) {
321            fail("Exception during getParameterTypes test:" + e.toString());
322        }
323        assertTrue("Incorrect parameter returned", types[0].equals(parms[0]));
324
325
326        try {
327            Constructor<GenericConstructorTestHelper> constructor = GenericConstructorTestHelper.class
328                    .getConstructor(Object.class, Object.class);
329            types = constructor.getGenericParameterTypes();
330        } catch (Exception e) {
331            fail("Exception during getParameterTypes test:" + e.toString());
332        }
333
334        assertEquals("Wrong number of parameter types returned", 2,
335                types.length);
336
337        assertEquals("Wrong number of parameter types returned", "T",
338                ((TypeVariable)types[0]).getName());
339        assertEquals("Wrong number of parameter types returned", "S",
340                ((TypeVariable)types[1]).getName());
341    }
342
343    @SuppressWarnings("unchecked")
344    public void test_getGenericExceptionTypes() {
345        Type[] types = null;
346
347        try {
348            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper()
349                    .getClass().getConstructor(new Class[0]);
350            types = ctor.getGenericExceptionTypes();
351        } catch (Exception e) {
352            fail("Exception during getGenericExceptionTypes test:" + e.toString());
353        }
354        assertEquals("Wrong number of exception types returned", 1, types.length);
355
356
357        try {
358            Constructor<GenericConstructorTestHelper> constructor = GenericConstructorTestHelper.class
359                    .getConstructor();
360            types = constructor.getGenericExceptionTypes();
361        } catch (Exception e) {
362            fail("Exception during getGenericExceptionTypes test:"
363                    + e.toString());
364        }
365
366        assertEquals("Wrong number of exception types returned", 1,
367                types.length);
368
369        assertEquals("Wrong exception name returned.", "E",
370                ((TypeVariable)types[0]).getName());
371
372    }
373
374
375    public void test_newInstance$Ljava_lang_Object() {
376        // Test for method java.lang.Object
377        // java.lang.reflect.Constructor.newInstance(java.lang.Object [])
378
379        ConstructorTestHelper test = null;
380        try {
381            Constructor<? extends ConstructorTestHelper> ctor = new ConstructorTestHelper().getClass()
382                    .getConstructor(new Class[0]);
383            test = ctor.newInstance((Object[])null);
384        } catch (Exception e) {
385            fail("Failed to create instance : " + e.getMessage());
386        }
387        assertEquals("improper instance created", 99, test.check());
388    }
389
390    public void test_toString() {
391        // Test for method java.lang.String
392        // java.lang.reflect.Constructor.toString()
393        Class[] parms = null;
394        Constructor<? extends ConstructorTestHelper> ctor = null;
395        try {
396            parms = new Class[1];
397            parms[0] = new Object().getClass();
398            ctor = new ConstructorTestHelper().getClass().getConstructor(parms);
399        } catch (Exception e) {
400            fail("Exception during getParameterTypes test:"
401                    + e.toString());
402        }
403        assertTrue(
404                "Returned incorrect string representation: " + ctor.toString(),
405                ctor
406                        .toString()
407                        .equals(
408                                "public tests.api.java.lang.reflect.ConstructorTest$ConstructorTestHelper(java.lang.Object)"));
409    }
410
411    public void test_getConstructor() throws Exception {
412        // Passing new Class[0] should be equivalent to (Class[]) null.
413        Class<ConstructorTestHelper> c2 = ConstructorTestHelper.class;
414        assertEquals(c2.getConstructor(new Class[0]), c2.getConstructor((Class[]) null));
415        assertEquals(c2.getDeclaredConstructor(new Class[0]),
416                     c2.getDeclaredConstructor((Class[]) null));
417
418        // We can get a non-public constructor via getDeclaredConstructor...
419        Class<NoPublicConstructorTestHelper> c1 = NoPublicConstructorTestHelper.class;
420        c1.getDeclaredConstructor((Class[]) null);
421        // ...but not with getConstructor (which only returns public constructors).
422        try {
423            c1.getConstructor((Class[]) null);
424            fail("Should throw NoSuchMethodException");
425        } catch (NoSuchMethodException ex) {
426            // Expected.
427        }
428    }
429
430    /**
431     * Sets up the fixture, for example, open a network connection. This method
432     * is called before a test is executed.
433     */
434    protected void setUp() {
435    }
436
437    /**
438     * Tears down the fixture, for example, close a network connection. This
439     * method is called after a test is executed.
440     */
441    protected void tearDown() {
442    }
443}
444