1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package complex.toolkit;
25 
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
28 import com.sun.star.uno.UnoRuntime;
29 import static org.junit.Assert.*;
30 
31 /**
32  * provides assertion capabilities not found in {@link org.junit.Assert}
33  * @author frank.schoenheit@oracle.com
34  */
35 public class Assert
36 {
37     // --------------------------------------------------------------------------------------------------------
38     /** invokes a given method on a given object, and assures a certain exception is caught
39      * @param i_message
40      *          is the message to print when the check fails
41      * @param i_object
42      *          is the object to invoke the method on
43      * @param i_methodName
44      *          is the name of the method to invoke
45      * @param i_methodArgs
46      *          are the arguments to pass to the method.
47      * @param i_argClasses
48      *          are the classes to assume for the arguments of the methods
49      * @param i_expectedExceptionClass
50      *          is the class of the exception to be caught. If this is null,
51      *          it means that <em>no</em> exception must be throw by invoking the method.
52     */
assertException( final String i_message, final Object i_object, final String i_methodName, final Class[] i_argClasses, final Object[] i_methodArgs, final Class i_expectedExceptionClass )53     public static void assertException( final String i_message, final Object i_object, final String i_methodName,
54         final Class[] i_argClasses, final Object[] i_methodArgs, final Class i_expectedExceptionClass )
55     {
56         Class objectClass = i_object.getClass();
57 
58         boolean noExceptionAllowed = ( i_expectedExceptionClass == null );
59 
60         boolean caughtExpected = noExceptionAllowed ? true : false;
61         try
62         {
63             Method method = impl_getMethod( objectClass, i_methodName, i_argClasses );
64             method.invoke(i_object, i_methodArgs );
65         }
66         catch ( NoSuchMethodException e )
67         {
68             StringBuilder message = new StringBuilder();
69             message.append( "no such method: " ).append( objectClass.getName() ).append( "." ).append( i_methodName ).append( "( " );
70             for ( int i=0; i<i_argClasses.length; ++i )
71             {
72                 message.append( i_argClasses[i].getName() );
73                 if ( i<i_argClasses.length - 1 )
74                     message.append( ", " );
75             }
76             message.append( " )" );
77             fail( message.toString() );
78         }
79         catch ( InvocationTargetException e )
80         {
81             caughtExpected =    noExceptionAllowed
82                             ?   false
83                             :   ( e.getTargetException().getClass().equals( i_expectedExceptionClass ) );
84         }
85         catch( Exception e )
86         {
87             caughtExpected = false;
88         }
89 
90         assertTrue( i_message, caughtExpected );
91     }
92 
93     /**
94      * retrieves a method, given by name and parameter signature, from the given class
95      *
96      * The method does somewhat more than simply calling {@link Class.getMethod}. In particular, it recognizes
97      * primitiive parameter types, and attempts to find a method taking the given primitive type, instead of the
98      * type represented by the parameter class.
99      *
100      * For instance, if you have a method <code>foo( int )</code>, {@link Class.getMethod} would not return this
101      * method when you pass <code>Integer.class</code>. <code>impl_getMethod</code> will recognize this, and
102      * properly retrieve the method.
103      *
104      * Note: <code>impl_getMethod</code> is limited in that it will not try all possible combinations of primitive
105      * and non-primitive types. That is, a method like <code>foo( int, Integer, int )</code> is likely to not be
106      * found.
107      *
108      * @param i_obbjectClass
109      * @param i_methodName
110      * @param i_argClasses
111      * @return
112      */
impl_getMethod( final Class i_objectClass, final String i_methodName, final Class[] i_argClasses )113     private static Method impl_getMethod( final Class i_objectClass, final String i_methodName, final Class[] i_argClasses ) throws NoSuchMethodException
114     {
115         try
116         {
117             return i_objectClass.getMethod( i_methodName, i_argClasses );
118         }
119         catch ( NoSuchMethodException ex )
120         {
121         }
122 
123         int substitutedTypes = 0;
124         int substitutedTypesLastRound = 0;
125         final Class[][] substitutionTable = new Class[][] {
126             new Class[] { Long.class, long.class },
127             new Class[] { Integer.class, int.class },
128             new Class[] { Short.class, short.class },
129             new Class[] { Byte.class, byte.class },
130             new Class[] { Double.class, double.class },
131             new Class[] { Float.class, float.class },
132             new Class[] { Character.class, char.class }
133         };
134         do
135         {
136             substitutedTypes = 0;
137             final Class[] argClasses = new Class[ i_argClasses.length ];
138             for ( int i=0; i < argClasses.length; ++i )
139             {
140                 argClasses[i] = i_argClasses[i];
141                 if ( substitutedTypes > substitutedTypesLastRound )
142                     continue;
143 
144                 for ( int c=0; c<substitutionTable.length; ++c )
145                 {
146                     if ( i_argClasses[i].equals( substitutionTable[c][0] ) )
147                     {
148                         argClasses[i] = substitutionTable[c][1];
149                         ++substitutedTypes;
150                         break;
151                     }
152                 }
153             }
154             if ( substitutedTypes == substitutedTypesLastRound )
155                 throw new NoSuchMethodException();
156             substitutedTypesLastRound = substitutedTypes;
157 
158             try
159             {
160                 return i_objectClass.getMethod( i_methodName, argClasses );
161             }
162             catch ( NoSuchMethodException e )
163             {
164             }
165         }
166         while ( substitutedTypes > 0 );
167         throw new NoSuchMethodException();
168     }
169 
170     /** invokes a given method on a given object, and assures a certain exception is caught
171      * @param i_message is the message to print when the check fails
172      * @param i_object is the object to invoke the method on
173      * @param i_methodName is the name of the method to invoke
174      * @param i_methodArgs are the arguments to pass to the method. Those implicitly define
175      *      the classes of the arguments of the method which is called.
176      * @param i_expectedExceptionClass is the class of the exception to be caught. If this is null,
177      *          it means that <em>no</em> exception must be throw by invoking the method.
178     */
assertException( final String i_message, final Object i_object, final String i_methodName, final Object[] i_methodArgs, final Class i_expectedExceptionClass )179     public static void assertException( final String i_message, final Object i_object, final String i_methodName,
180         final Object[] i_methodArgs, final Class i_expectedExceptionClass )
181     {
182         Class[] argClasses = new Class[ i_methodArgs.length ];
183         for ( int i=0; i<i_methodArgs.length; ++i )
184             argClasses[i] = i_methodArgs[i].getClass();
185         assertException( i_message, i_object, i_methodName, argClasses, i_methodArgs, i_expectedExceptionClass );
186     }
187 
188     /** invokes a given method on a given object, and assures a certain exception is caught
189      * @param i_object is the object to invoke the method on
190      * @param i_methodName is the name of the method to invoke
191      * @param i_methodArgs are the arguments to pass to the method. Those implicitly define
192      *      the classes of the arguments of the method which is called.
193      * @param i_expectedExceptionClass is the class of the exception to be caught. If this is null,
194      *          it means that <em>no</em> exception must be throw by invoking the method.
195     */
assertException( final Object i_object, final String i_methodName, final Object[] i_methodArgs, final Class i_expectedExceptionClass )196     public static void assertException( final Object i_object, final String i_methodName, final Object[] i_methodArgs,
197         final Class i_expectedExceptionClass )
198     {
199         assertException(
200             "did not catch the expected exception (" +
201                 ( ( i_expectedExceptionClass == null ) ? "none" : i_expectedExceptionClass.getName() ) +
202                 ") while calling " + i_object.getClass().getName() + "." + i_methodName,
203             i_object, i_methodName, i_methodArgs, i_expectedExceptionClass );
204     }
205 
206     /** invokes a given method on a given object, and assures a certain exception is caught
207      * @param i_object is the object to invoke the method on
208      * @param i_methodName is the name of the method to invoke
209      * @param i_methodArgs are the arguments to pass to the method
210      * @param i_argClasses are the classes to assume for the arguments of the methods
211      * @param i_expectedExceptionClass is the class of the exception to be caught. If this is null,
212      *          it means that <em>no</em> exception must be throw by invoking the method.
213     */
assertException( final Object i_object, final String i_methodName, final Class[] i_argClasses, final Object[] i_methodArgs, final Class i_expectedExceptionClass )214     public static void assertException( final Object i_object, final String i_methodName, final Class[] i_argClasses,
215         final Object[] i_methodArgs, final Class i_expectedExceptionClass )
216     {
217         assertException(
218             "did not catch the expected exception (" +
219                 ( ( i_expectedExceptionClass == null ) ? "none" : i_expectedExceptionClass.getName() ) +
220                 ") while calling " + i_object.getClass().getName() + "." + i_methodName,
221             i_object, i_methodName, i_argClasses, i_methodArgs, i_expectedExceptionClass );
222     }
223 
224     // --------------------------------------------------------------------------------------------------------
assertException( Object i_object, Class _unoInterfaceClass, String i_methodName, Object[] i_methodArgs, Class i_expectedExceptionClass )225     public static void assertException( Object i_object, Class _unoInterfaceClass, String i_methodName, Object[] i_methodArgs,
226         Class i_expectedExceptionClass )
227     {
228         assertException( UnoRuntime.queryInterface( _unoInterfaceClass, i_object ), i_methodName,
229             i_methodArgs, i_expectedExceptionClass );
230     }
231 }
232