Initial import
[jpf-core.git] / src / tests / gov / nasa / jpf / test / vm / reflection / MethodTest.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18 package gov.nasa.jpf.test.vm.reflection;
19
20 import gov.nasa.jpf.util.test.TestJPF;
21
22 import java.lang.annotation.Annotation;
23 import java.lang.annotation.Retention;
24 import java.lang.annotation.RetentionPolicy;
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.Method;
27
28 import org.junit.Test;
29
30 public class MethodTest extends TestJPF {
31
32   private double m_data = 42.0;
33   private Object m_arg;
34
35   static class Boo {
36
37     static int d = 42;
38   }
39
40   static class Faz {
41
42     static int d = 4200;
43     
44     static private int foo (int a){
45       return a + 42;
46     }
47   }
48
49   static class SupC {
50
51     private int privateMethod() {
52       return -42;
53     }
54   }
55
56   static class SubC extends SupC {
57
58     public int privateMethod() {
59       return 42;
60     }
61   }
62
63   public Boo getBoo() {
64     return null;
65   }
66
67   public double foo(int a, double d, String s) {
68     System.out.printf("in foo( %d, %f, %s)\n", a,d,s);
69     
70     assert m_data == 42.0 : "wrong object data";
71     assert a == 3 : "wrong int parameter value";
72     assert d == 3.33 : "wrong double parameter value";
73     assert "Blah".equals(s) : "wrong String parameter value";
74
75     return 123.456;
76   }
77
78   @Test
79   public void testInstanceMethodInvoke() {
80     if (verifyNoPropertyViolation()) {
81       MethodTest o = new MethodTest();
82
83       try {
84         Class<?> cls = o.getClass();
85         Method m = cls.getMethod("foo", int.class, double.class, String.class);
86
87         Object res = m.invoke(o, new Integer(3), new Double(3.33), "Blah");
88         double d = ((Double) res).doubleValue();
89         System.out.println("foo returned " + d);
90
91         assert d == 123.456 : "wrong return value";
92
93       } catch (Throwable t) {
94         t.printStackTrace();
95
96         assert false : " unexpected exception: " + t;
97       }
98     }
99   }
100
101   public static int harr (int a){
102     System.out.printf("in harr(%d)\n", a);
103     
104     return a+1;
105   }
106   
107   @Test
108   public void testStaticMethodInvoke() {
109     if (verifyNoPropertyViolation()) {
110       MethodTest o = new MethodTest();
111
112       try {
113         Class<?> cls = o.getClass();
114         Method m = cls.getMethod("harr", int.class);
115
116         Object res = m.invoke(null, new Integer(41));
117         int r = (Integer)res;
118         System.out.println("harr returned " + r);
119
120         assert r == 42 : "wrong return value";
121
122       } catch (Throwable t) {
123         t.printStackTrace();
124
125         assert false : " unexpected exception: " + t;
126       }
127     }
128   }
129   
130   public static void doAlmostNothing(){
131     System.out.println("in doAlmostNothing");
132   }
133   
134   @Test
135   public void testNoArgStaticMethodInvoke() {
136     if (verifyNoPropertyViolation()) {
137       MethodTest o = new MethodTest();
138
139       try {
140         Class<?> cls = o.getClass();
141         Method m = cls.getMethod("doAlmostNothing");
142
143         Object res = m.invoke(null, (Object[])null);
144         System.out.println("doAlmostNothing returned " + res);
145
146         assert res == null : "wrong return value";
147
148       } catch (Throwable t) {
149         t.printStackTrace();
150
151         assert false : " unexpected exception: " + t;
152       }
153     }
154   }
155   
156   
157   
158   @Test
159   public void getPrivateMethod() throws NoSuchMethodException {
160     if (verifyUnhandledException(NoSuchMethodException.class.getName())) {
161       Integer.class.getMethod("toUnsignedString0", int.class, int.class);   // Doesn't matter which class we use.  It just needs to be a different class and a private method.
162     }
163   }
164
165   private static void privateStaticMethod() {
166   }
167
168   @Test
169   public void invokePrivateSameClass() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
170     privateStaticMethod();   // Get rid of IDE warning
171
172     if (verifyNoPropertyViolation()) {
173       Method m = getClass().getDeclaredMethod("privateStaticMethod");
174
175       m.invoke(null);
176     }
177   }
178
179   @Test
180   public void invokePrivateOtherClass() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
181     if (verifyUnhandledException(IllegalAccessException.class.getName())) {
182       Method m = Faz.class.getDeclaredMethod("foo", int.class);
183
184       int res = (Integer)m.invoke(null, 5);
185       fail("should never get here");
186     }
187   }
188
189   @Test
190   public void invokePrivateOtherClassAccessible() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
191     if (verifyNoPropertyViolation()) {
192       Method m = Faz.class.getDeclaredMethod("foo", int.class);
193
194       m.setAccessible(true);
195       int res = (Integer)m.invoke(null, 5);
196       assertTrue( res == 47);
197     }
198   }
199
200   @Test
201   public void invokePrivateSuperclass() throws SecurityException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
202     if (verifyNoPropertyViolation()) {
203       Method aMethod = SupC.class.getDeclaredMethod("privateMethod");
204       aMethod.setAccessible(true);
205       assert ((Integer) aMethod.invoke(new SubC()) == -42) : "must call method from superclass";
206     }
207   }
208
209   @Test
210   public void getMethodCanFindNotify() throws NoSuchMethodException {
211     if (verifyNoPropertyViolation()) {
212       Integer.class.getMethod("notify");
213     }
214   }
215
216   @Test
217   public void getDeclaredMethodCantFindNotify() throws NoSuchMethodException {
218     if (verifyUnhandledException(NoSuchMethodException.class.getName())) {
219       Integer.class.getDeclaredMethod("notify");
220     }
221   }
222
223   public void publicMethod() {
224   }
225
226   @Test
227   public void invokeWrongThisType() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
228     if (verifyUnhandledException(IllegalArgumentException.class.getName())) {
229       Method m = getClass().getMethod("publicMethod");
230
231       m.invoke(new Object());
232     }
233   }
234
235   @Test
236   public void invokeNullObject() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
237     if (verifyUnhandledException(NullPointerException.class.getName())) {
238       Method m = getClass().getMethod("publicMethod");
239
240       m.invoke(null);
241     }
242   }
243
244   @Test
245   public void invokeWrongNumberOfArguments() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
246     if (verifyUnhandledException(IllegalArgumentException.class.getName())) {
247       Method m = getClass().getMethod("publicMethod");
248
249       m.invoke(this, 5);
250     }
251   }
252
253   @Test
254   public void invokeWrongArgumentTypeReference() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
255     if (verifyUnhandledException(IllegalArgumentException.class.getName())) {
256       Method m = getClass().getMethod("boofaz", Boo.class, Faz.class);
257
258       m.invoke(this, new Faz(), new Boo());
259     }
260   }
261
262   public void throwThrowable() throws Throwable {
263     throw new Throwable("purposeful exception");
264   }
265
266   @Test
267   public void invokeInvocationTargetException() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
268     Class<?> clazz;
269     Method method;
270
271     if (verifyUnhandledException(InvocationTargetException.class.getName())) {
272       clazz = getClass();
273       method = clazz.getMethod("throwThrowable");
274
275       method.invoke(this);
276     }
277   }
278
279   @Test
280   public void testReturnType() {
281     if (verifyNoPropertyViolation()) {
282       MethodTest o = new MethodTest();
283
284       try {
285         Class<?> cls = o.getClass();
286         Method m = cls.getMethod("getBoo");
287         Class<?> rt = m.getReturnType();
288         String s = rt.getName();
289
290         assert Boo.class.getName().equals(s) : "wrong return type: " + s;
291
292       } catch (Throwable t) {
293         t.printStackTrace();
294
295         assert false : " unexpected exception in Method.getReturnType(): " + t;
296       }
297     }
298   }
299
300   public void boofaz(Boo b, Faz f) {
301     b = null; // Get rid of IDE warning
302     f = null;
303   }
304
305   @Test
306   public void testParameterTypes() {
307     if (verifyNoPropertyViolation()) {
308       MethodTest o = new MethodTest();
309
310       try {
311         Class<?> cls = o.getClass();
312
313         for (Method m : cls.getMethods()) {
314           if (m.getName().equals("boofaz")) {
315             Class<?>[] pt = m.getParameterTypes();
316
317             assert Boo.class.getName().equals(pt[0].getName()) : "wrong parameter type 0: " + pt[0].getName();
318             assert Faz.class.getName().equals(pt[1].getName()) : "wrong parameter type 1: " + pt[1].getName();
319           }
320         }
321
322       } catch (Throwable t) {
323         t.printStackTrace();
324
325         assert false : " unexpected exception in Method.getParameterTypes(): " + t;
326       }
327     }
328   }
329
330   //--- argument value conversion tests
331   
332   static final Object[] testArgValues = {
333     Byte.valueOf((byte) 7),
334     Short.valueOf((short) 8),
335     Integer.valueOf(9),
336     Long.valueOf(10),
337     Float.valueOf(3.1415f),
338     Double.valueOf(3.14159),
339     Boolean.TRUE,
340     Character.valueOf('w'),
341     "hello",
342     null
343   };
344   
345   static final Object ILLEGAL = new Object(); // we use this to flag an IllegalArgumentException
346   
347   private void invokeTest (Method m, Object argValue, Object expected){
348     System.out.print(argValue);
349     System.out.print("=>");
350     try {
351       Object ret = m.invoke(this, argValue);
352       System.out.println(ret);
353       if (isJPFRun()) {
354         assertTrue( ((ret == null) && (expected == null)) || ret.equals(expected));
355       }
356       
357     } catch (IllegalArgumentException ix){
358       System.out.println("ILLEGAL");
359       if (isJPFRun()) {
360         assertTrue( expected == ILLEGAL);
361       }
362       
363     } catch (Throwable t){
364       fail("_test invocation failed for value = " + argValue + " with " + t);
365     }    
366   }
367
368   //--- boolean argument
369   
370   boolean _test (boolean v){
371     //System.out.println("-- test(boolean) got " + v);
372     return v;    
373   }
374   
375   @Test
376   public void argTestBoolean() throws NoSuchMethodException {
377     if (verifyNoPropertyViolation()){
378       Method m = MethodTest.class.getDeclaredMethod("_test", boolean.class);
379       Object[] expected = { // all but Boolean throws
380           ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, Boolean.TRUE, ILLEGAL, ILLEGAL, ILLEGAL
381       };
382
383       for (int i=0; i<testArgValues.length; i++){
384         invokeTest( m, testArgValues[i], expected[i]);
385       }
386     }
387   }
388   
389   //--- byte argument
390   byte _test(byte v){
391     //System.out.println("-- test(long) got " + v);
392     return v;
393   }
394   
395   @Test
396   public void argTestByte() throws NoSuchMethodException {
397     if (verifyNoPropertyViolation()){
398       Method m = MethodTest.class.getDeclaredMethod("_test", byte.class);
399       Object[] expected = { // all but byte throws
400           Byte.valueOf((byte)7), ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL
401       };
402       
403       for (int i=0; i<testArgValues.length; i++){
404         invokeTest( m, testArgValues[i], expected[i]);
405       }
406     }    
407   }
408   
409   //--- short argument
410   short _test(short v){
411     //System.out.println("-- test(short) got " + v);
412     return v;
413   }
414   
415   @Test
416   public void argTestShort() throws NoSuchMethodException {
417     if (verifyNoPropertyViolation()){
418       Method m = MethodTest.class.getDeclaredMethod("_test", short.class);
419       Object[] expected = { // all but byte and short throws
420           Short.valueOf((short)7), Short.valueOf((short)8), ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL
421       };
422       
423       for (int i=0; i<testArgValues.length; i++){
424         invokeTest( m, testArgValues[i], expected[i]);
425       }
426     }    
427   }
428
429   //--- char argument
430   char _test(char v){
431     //System.out.println("-- test(char) got " + v);
432     return v;
433   }
434   
435   @Test
436   public void argTestChar() throws NoSuchMethodException {
437     if (verifyNoPropertyViolation()){
438       Method m = MethodTest.class.getDeclaredMethod("_test", char.class);
439       Object[] expected = { // all but char throws
440           ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, Character.valueOf('w'), ILLEGAL, ILLEGAL
441       };
442       
443       for (int i=0; i<testArgValues.length; i++){
444         invokeTest( m, testArgValues[i], expected[i]);
445       }
446     }    
447   }
448
449
450   //--- int argument
451   int _test(int v){
452     //System.out.println("-- test(int) got " + v);
453     return v;
454   }
455   
456   @Test
457   public void argTestInt() throws NoSuchMethodException {
458     if (verifyNoPropertyViolation()){
459       Method m = MethodTest.class.getDeclaredMethod("_test", int.class);
460       Object[] expected = { // all but byte, short, int and char throws
461           Integer.valueOf(7), Integer.valueOf(8), Integer.valueOf(9), ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
462           Integer.valueOf('w'), ILLEGAL, ILLEGAL
463       };
464       
465       for (int i=0; i<testArgValues.length; i++){
466         invokeTest( m, testArgValues[i], expected[i]);
467       }
468     }    
469   }
470
471   
472   //--- long argument
473   long _test(long v){
474     //System.out.println("-- test(long) got " + v);
475     return v;
476   }
477   
478   @Test
479   public void argTestLong() throws NoSuchMethodException {
480     if (verifyNoPropertyViolation()){
481       Method m = MethodTest.class.getDeclaredMethod("_test", long.class);
482       Object[] expected = {
483           Long.valueOf(7L),Long.valueOf(8L), Long.valueOf(9L), Long.valueOf(10L),
484           ILLEGAL, ILLEGAL, ILLEGAL, Long.valueOf('w'), ILLEGAL, ILLEGAL
485       };
486       
487       for (int i=0; i<testArgValues.length; i++){
488         invokeTest( m, testArgValues[i], expected[i]);
489       }
490     }
491   }
492
493   //--- float argument
494   float _test(float v){
495     //System.out.println("-- test(float) got " + v);
496     return v;
497   }
498   
499   @Test
500   public void argTestFloat() throws NoSuchMethodException {
501     if (verifyNoPropertyViolation()){
502       Method m = MethodTest.class.getDeclaredMethod("_test", float.class);
503       Object[] expected = {
504           Float.valueOf(7f), Float.valueOf(8f), Float.valueOf(9f), 
505           Float.valueOf(10f), Float.valueOf(3.1415f), ILLEGAL, ILLEGAL, 
506           Float.valueOf('w'), ILLEGAL, ILLEGAL
507       };
508       
509       for (int i=0; i<testArgValues.length; i++){
510         invokeTest( m, testArgValues[i], expected[i]);
511       }
512     }
513   }
514
515   //--- double argument
516   double _test(double v){
517     //System.out.println("-- test(double) got " + v);
518     return v;
519   }
520   
521   @Test
522   public void argTestDouble() throws NoSuchMethodException {
523     if (verifyNoPropertyViolation()){
524       Method m = MethodTest.class.getDeclaredMethod("_test", double.class);
525       Object[] expected = {
526           Double.valueOf(7.0), Double.valueOf(8.0), Double.valueOf(9.0), 
527           Double.valueOf(10.0), Double.valueOf(3.1415f), Double.valueOf(3.14159),
528           ILLEGAL, Double.valueOf('w'), ILLEGAL, ILLEGAL
529       };
530       
531       for (int i=0; i<testArgValues.length; i++){
532         invokeTest( m, testArgValues[i], expected[i]);
533       }
534     }
535   }
536
537   //--- String argument
538   String _test(String v){
539     //System.out.println("-- test(String) got " + v);
540     return v;
541   }
542   
543   @Test
544   public void argTestString() throws NoSuchMethodException {
545     if (verifyNoPropertyViolation()){
546       Method m = MethodTest.class.getDeclaredMethod("_test", String.class);
547       Object[] expected = {
548           ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, "hello", null
549       };
550       
551       for (int i=0; i<testArgValues.length; i++){
552         invokeTest( m, testArgValues[i], expected[i]);
553       }
554     }
555   }
556   
557   //--- Object argument
558   Object _test(Object v){
559     //System.out.println("-- test(String) got " + v);
560     return v;
561   }
562   
563   @Test
564   public void argTestObject() throws NoSuchMethodException {
565     if (verifyNoPropertyViolation()){
566       Method m = MethodTest.class.getDeclaredMethod("_test", Object.class);
567       Object[] expected = testArgValues;
568       
569       for (int i=0; i<testArgValues.length; i++){
570         invokeTest( m, testArgValues[i], expected[i]);
571       }
572     }
573   }
574
575   //--- Number argument
576   Number _test(Number v){
577     //System.out.println("-- test(Number) got " + v);
578     return v;
579   }
580   
581   @Test
582   public void argTestNumber() throws NoSuchMethodException {
583     if (verifyNoPropertyViolation()){
584       Method m = MethodTest.class.getDeclaredMethod("_test", Number.class);
585       Object[] expected = {
586           Byte.valueOf((byte) 7),
587           Short.valueOf((short) 8),
588           Integer.valueOf(9),
589           Long.valueOf(10),
590           Float.valueOf(3.1415f),
591           Double.valueOf(3.14159),
592           ILLEGAL,
593           ILLEGAL,
594           ILLEGAL,
595           null  // we already used the real null to flag an IllegalArgumentException
596        };
597       
598       for (int i=0; i<testArgValues.length; i++){
599         invokeTest( m, testArgValues[i], expected[i]);
600       }
601     }
602   }
603
604   //--- array argument
605   int[] _test(int[] v){
606     //System.out.println("-- test(int[]) got " + v);
607     return v;
608   }
609   
610   @Test
611   public void argTestIntArray() throws NoSuchMethodException {
612     if (verifyNoPropertyViolation()){
613       Method m = MethodTest.class.getDeclaredMethod("_test", int[].class);
614       Object[] testVals = {
615         new int[0],
616         new float[0],
617         "blah",
618         null
619       };
620       Object[] expected = {
621           testVals[0],
622           ILLEGAL,
623           ILLEGAL,
624           null
625        };
626       
627       for (int i=0; i<testVals.length; i++){
628         invokeTest( m, testVals[i], expected[i]);
629       }
630     }
631   }
632
633   
634   //--- parameter annotation reflection
635   
636   @Retention(RetentionPolicy.RUNTIME)
637   @interface A {
638     String value();
639   }
640   
641   void noFoo() {}
642   void noFoo(int a) {}
643   void oneFoo (@A("arg 1")int a){}
644   void twoFoo (int a, @A("arg 2") int b){}
645   
646   @Test
647   public void testParameterAnnotations(){
648     if (verifyNoPropertyViolation()){
649       try {
650         Method mth;
651         Annotation[][] pai;
652         Class<MethodTest> cls = MethodTest.class;
653 /**
654         mth = cls.getDeclaredMethod("noFoo");
655         pai = mth.getParameterAnnotations();
656         assertTrue("should return Annotation[0][] for noFoo()", pai != null && pai.length == 0);
657         
658         mth = cls.getDeclaredMethod("noFoo", int.class );
659         pai = mth.getParameterAnnotations();
660         assertTrue("should return Annotation[1][{}] for noFoo(int)", pai != null && pai.length == 1 
661             && ((pai[0] != null) && (pai[0].length == 0)));
662         System.out.println("noFoo(int) : " + pai[0]);
663 **/
664         mth = cls.getDeclaredMethod("oneFoo", int.class);
665         pai = mth.getParameterAnnotations();
666         assertTrue("should return Annotation[1][{@A}] for oneFoo(int)", pai != null && pai.length == 1 
667             && ((pai[0] != null) && (pai[0].length == 1) && (pai[0][0] instanceof A)));
668         System.out.println("oneFoo(@A int) : " + pai[0][0]);
669
670         mth = cls.getDeclaredMethod("twoFoo", int.class, int.class);
671         pai = mth.getParameterAnnotations();
672         assertTrue("should return Annotation[1][{@A}{}] for twoFoo(int,int)", pai != null && pai.length == 2 
673             && ((pai[0] != null) && (pai[0].length == 0))
674             && ((pai[1] != null) && (pai[1].length == 1)  && (pai[1][0] instanceof A)));
675         System.out.println("twoFoo(int, @A int)  : " + pai[0] + ',' +  pai[1][0]);
676         
677         
678       } catch (Throwable t){
679         t.printStackTrace();
680         fail("retrieving parameter annotation failed: " + t);
681       }
682
683     }
684   }
685   
686 }