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