001package org.apache.commons.beanutils2;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one or more
005 * contributor license agreements.  See the NOTICE file distributed with
006 * this work for additional information regarding copyright ownership.
007 * The ASF licenses this file to You under the Apache License, Version 2.0
008 * (the "License"); you may not use this file except in compliance with
009 * the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020import static java.lang.String.format;
021import static java.lang.reflect.Modifier.isPublic;
022import static org.junit.Assert.assertArrayEquals;
023import static org.junit.Assert.assertEquals;
024import static org.junit.Assert.assertNotNull;
025import static org.junit.Assert.assertNull;
026import static org.junit.Assert.assertTrue;
027
028import java.lang.reflect.Constructor;
029
030import org.apache.commons.beanutils2.testbeans.TestBean;
031import org.junit.Test;
032
033public class ConstructorRegistryTestCase
034{
035
036    private static final String WRONG_FOUND = "ConstructorRegistry resolved wrong constructor!";
037
038    private static final String NON_FOUND = "ConstructorRegistry could not resolve constructor %s!";
039
040    private final AccessibleObjectsRegistry<Constructor<?>> constructorRegistry =
041        AccessibleObjectsRegistry.getConstructorsRegistry();
042
043    @Test
044    public void get()
045    {
046        Constructor<?>[] constructors = TestBean.class.getConstructors();
047        for ( Constructor<?> constructor : constructors )
048        {
049            Constructor<?> resolved = constructorRegistry.get( false, TestBean.class, constructor.getParameterTypes() );
050            assertNotNull( format( NON_FOUND, constructor ), resolved );
051            assertEquals( WRONG_FOUND, constructor, resolved );
052        }
053    }
054
055    @Test
056    public void getDifferentParameter()
057        throws Exception
058    {
059        Constructor<TestBean> floatConstructor = TestBean.class.getConstructor( float.class );
060        Constructor<?> resolved = constructorRegistry.get( false, TestBean.class, Float.class );
061        assertNotNull( format( NON_FOUND, floatConstructor ), resolved );
062        assertEquals( WRONG_FOUND, floatConstructor, resolved );
063    }
064
065    @Test
066    public void getExact()
067    {
068        Constructor<?>[] constructors = TestBean.class.getConstructors();
069        for ( Constructor<?> constructor : constructors )
070        {
071            Constructor<?> resolved = constructorRegistry.get( true, TestBean.class, constructor.getParameterTypes() );
072            assertNotNull( format( NON_FOUND, constructor ), resolved );
073            assertEquals( WRONG_FOUND, constructor, resolved );
074        }
075    }
076
077    @Test
078    public void getExactDifferentParameter()
079        throws Exception
080    {
081        Constructor<?> resolved = constructorRegistry.get( true, TestBean.class, Float.class );
082        assertNull( format( "Constructor resolved constructor [%s] for parameter type Float on type TestBean although TestBean does not describe such a constructor.",
083                            resolved ), resolved );
084    }
085
086    @Test
087    public void getWithName()
088    {
089        // TODO does the constructorRegistry need this method? constructors don't have names.
090        Constructor<?>[] constructors = TestBean.class.getConstructors();
091        for ( Constructor<?> constructor : constructors )
092        {
093            Constructor<?> resolved = constructorRegistry.get( true, TestBean.class,
094                                                               "name is ignored by Constructors Registry",
095                                                               constructor.getParameterTypes() );
096            assertNotNull( format( NON_FOUND, constructor ), resolved );
097            assertEquals( WRONG_FOUND, constructor, resolved );
098        }
099    }
100
101    @Test
102    public void resolveDirectly()
103        throws Exception
104    {
105        Constructor<?>[] constructors = TestBean.class.getConstructors();
106        for ( Constructor<?> constructor : constructors )
107        {
108            Constructor<?> resolved =
109                constructorRegistry.resolveDirectly( TestBean.class, null, constructor.getParameterTypes() );
110            assertNotNull( format( NON_FOUND, constructor ), resolved );
111            assertEquals( WRONG_FOUND, constructor, resolved );
112        }
113    }
114
115    @Test
116    public void getAccessibleObjectsArrayForTestBean()
117    {
118        Constructor<?>[] constructors = constructorRegistry.getAccessibleObjectsArray( TestBean.class );
119        assertNotNull( constructors );
120        assertArrayEquals( TestBean.class.getConstructors(), constructors );
121    }
122
123    @Test
124    public void matchesNull()
125    {
126        // this method always returns true
127        boolean matches = constructorRegistry.matches( null, null );
128        assertTrue( matches );
129    }
130
131    @Test
132    public void matches()
133    {
134        // this method always returns true
135        Constructor<?>[] constructors = TestBean.class.getConstructors();
136        for ( Constructor<?> constructor : constructors )
137        {
138            boolean matches = constructorRegistry.matches( constructor, "this returns true" );
139            assertTrue( matches );
140        }
141    }
142
143    @Test
144    public void getParameterTypes()
145    {
146        Constructor<?>[] constructors = TestBean.class.getDeclaredConstructors();
147        for ( Constructor<?> constructor : constructors )
148        {
149            Class<?>[] typesFromRegistry = constructorRegistry.getParameterTypes( constructor );
150            assertArrayEquals( constructor.getParameterTypes(), typesFromRegistry );
151        }
152    }
153
154    @Test
155    public void resolveAccessibleNull()
156    {
157        assertNull( constructorRegistry.resolveAccessible( Object.class, null ) );
158    }
159
160    @Test
161    public void resolveAccessible()
162    {
163        Constructor<?>[] constructors = TestBean.class.getDeclaredConstructors();
164        for ( Constructor<?> constructor : constructors )
165        {
166            Constructor<?> resolved = constructorRegistry.resolveAccessible( TestBean.class, constructor );
167            if ( isPublic( constructor.getModifiers() ) )
168            {
169                assertEquals( constructor, resolved );
170            }
171            else
172            {
173                assertNull( resolved );
174            }
175        }
176    }
177
178    @Test
179    public void resolveAccessiblePrivateClass()
180    {
181        Constructor<?>[] constructors = PrivateTestBean.class.getDeclaredConstructors();
182        for ( Constructor<?> constructor : constructors )
183        {
184            Constructor<?> resolved = constructorRegistry.resolveAccessible( TestBean.class, constructor );
185            // PrivateTestBean is a private class, so no constructor is accessible.
186            assertNull( resolved );
187        }
188    }
189
190    @SuppressWarnings( "unused" ) // class is used for tests only
191    private static class PrivateTestBean
192    {
193
194        public PrivateTestBean()
195        {
196            // empty default constructor
197        }
198
199        private PrivateTestBean( int i )
200        {
201            // int constructor
202        }
203    }
204
205}