// // Copyright (C) 2006 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.test.vm.reflection; import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.junit.Test; import gov.nasa.jpf.util.test.TestJPF; @SuppressWarnings({ "unused" }) public class MethodTest extends TestJPF { private double m_data = 42.0; private Object m_arg; static class Boo { static int d = 42; } static class Faz { static int d = 4200; } static class SupC { private int privateMethod() { return -42; } } static class SubC extends SupC { public int privateMethod() { return 42; } } public Boo getBoo() { return null; } public double foo(int a, double d, String s) { System.out.printf("in foo( %d, %f, %s)\n", a,d,s); assert m_data == 42.0 : "wrong object data"; assert a == 3 : "wrong int parameter value"; assert d == 3.33 : "wrong double parameter value"; assert "Blah".equals(s) : "wrong String parameter value"; return 123.456; } @Test public void testInstanceMethodInvoke() { if (verifyNoPropertyViolation()) { MethodTest o = new MethodTest(); try { Class<?> cls = o.getClass(); Method m = cls.getMethod("foo", int.class, double.class, String.class); Object res = m.invoke(o, new Integer(3), new Double(3.33), "Blah"); double d = ((Double) res).doubleValue(); System.out.println("foo returned " + d); assert d == 123.456 : "wrong return value"; } catch (Throwable t) { t.printStackTrace(); assert false : " unexpected exception: " + t; } } } public static int harr (int a){ System.out.printf("in harr(%d)\n", a); return a+1; } @Test public void testStaticMethodInvoke() { if (verifyNoPropertyViolation()) { MethodTest o = new MethodTest(); try { Class<?> cls = o.getClass(); Method m = cls.getMethod("harr", int.class); Object res = m.invoke(null, new Integer(41)); int r = (Integer)res; System.out.println("harr returned " + r); assert r == 42 : "wrong return value"; } catch (Throwable t) { t.printStackTrace(); assert false : " unexpected exception: " + t; } } } public static void doAlmostNothing(){ System.out.println("in doAlmostNothing"); } @Test public void testNoArgStaticMethodInvoke() { if (verifyNoPropertyViolation()) { MethodTest o = new MethodTest(); try { Class<?> cls = o.getClass(); Method m = cls.getMethod("doAlmostNothing"); Object res = m.invoke(null, (Object[])null); System.out.println("doAlmostNothing returned " + res); assert res == null : "wrong return value"; } catch (Throwable t) { t.printStackTrace(); assert false : " unexpected exception: " + t; } } } @Test public void getPrivateMethod() throws NoSuchMethodException { if (verifyUnhandledException(NoSuchMethodException.class.getName())) { 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. } } private static void privateStaticMethod() { } @Test public void invokePrivateSameClass() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { privateStaticMethod(); // Get rid of IDE warning if (verifyNoPropertyViolation()) { Method m = getClass().getDeclaredMethod("privateStaticMethod"); m.invoke(null); } } @Test public void invokePrivateOtherClass() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (verifyUnhandledException(IllegalAccessException.class.getName())) { Method m = Integer.class.getDeclaredMethod("toUnsignedString0", int.class, int.class); m.invoke(null, 5, 3); } } @Test public void invokePrivateOtherClassAccessible() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (verifyNoPropertyViolation()) { Method m = Integer.class.getDeclaredMethod("toUnsignedString0", int.class, int.class); m.setAccessible(true); m.invoke(null, 5, 3); } } @Test public void invokePrivateSuperclass() throws SecurityException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (verifyNoPropertyViolation()) { Method aMethod = SupC.class.getDeclaredMethod("privateMethod"); aMethod.setAccessible(true); assert ((Integer) aMethod.invoke(new SubC()) == -42) : "must call method from superclass"; } } @Test public void getMethodCanFindNotify() throws NoSuchMethodException { if (verifyNoPropertyViolation()) { Integer.class.getMethod("notify"); } } @Test public void getDeclaredMethodCantFindNotify() throws NoSuchMethodException { if (verifyUnhandledException(NoSuchMethodException.class.getName())) { Integer.class.getDeclaredMethod("notify"); } } public void publicMethod() { } @Test public void invokeWrongThisType() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (verifyUnhandledException(IllegalArgumentException.class.getName())) { Method m = getClass().getMethod("publicMethod"); m.invoke(new Object()); } } @Test public void invokeNullObject() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (verifyUnhandledException(NullPointerException.class.getName())) { Method m = getClass().getMethod("publicMethod"); m.invoke(null); } } @Test public void invokeWrongNumberOfArguments() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (verifyUnhandledException(IllegalArgumentException.class.getName())) { Method m = getClass().getMethod("publicMethod"); m.invoke(this, 5); } } @Test public void invokeWrongArgumentTypeReference() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (verifyUnhandledException(IllegalArgumentException.class.getName())) { Method m = getClass().getMethod("boofaz", Boo.class, Faz.class); m.invoke(this, new Faz(), new Boo()); } } public void throwThrowable() throws Throwable { throw new Throwable("purposeful exception"); } @Test public void invokeInvocationTargetException() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Class<?> clazz; Method method; if (verifyUnhandledException(InvocationTargetException.class.getName())) { clazz = getClass(); method = clazz.getMethod("throwThrowable"); method.invoke(this); } } @Test public void testReturnType() { if (verifyNoPropertyViolation()) { MethodTest o = new MethodTest(); try { Class<?> cls = o.getClass(); Method m = cls.getMethod("getBoo"); Class<?> rt = m.getReturnType(); String s = rt.getName(); assert Boo.class.getName().equals(s) : "wrong return type: " + s; } catch (Throwable t) { t.printStackTrace(); assert false : " unexpected exception in Method.getReturnType(): " + t; } } } public void boofaz(Boo b, Faz f) { b = null; // Get rid of IDE warning f = null; } @Test public void testParameterTypes() { if (verifyNoPropertyViolation()) { MethodTest o = new MethodTest(); try { Class<?> cls = o.getClass(); for (Method m : cls.getMethods()) { if (m.getName().equals("boofaz")) { Class<?>[] pt = m.getParameterTypes(); assert Boo.class.getName().equals(pt[0].getName()) : "wrong parameter type 0: " + pt[0].getName(); assert Faz.class.getName().equals(pt[1].getName()) : "wrong parameter type 1: " + pt[1].getName(); } } } catch (Throwable t) { t.printStackTrace(); assert false : " unexpected exception in Method.getParameterTypes(): " + t; } } } //--- argument value conversion tests static final Object[] testArgValues = { Byte.valueOf((byte) 7), Short.valueOf((short) 8), Integer.valueOf(9), Long.valueOf(10), Float.valueOf(3.1415f), Double.valueOf(3.14159), Boolean.TRUE, Character.valueOf('w'), "hello", null }; static final Object ILLEGAL = new Object(); // we use this to flag an IllegalArgumentException private void invokeTest (Method m, Object argValue, Object expected){ System.out.print(argValue); System.out.print("=>"); try { Object ret = m.invoke(this, argValue); System.out.println(ret); if (isJPFRun()) { assertTrue( ((ret == null) && (expected == null)) || ret.equals(expected)); } } catch (IllegalArgumentException ix){ System.out.println("ILLEGAL"); if (isJPFRun()) { assertTrue( expected == ILLEGAL); } } catch (Throwable t){ fail("_test invocation failed for value = " + argValue + " with " + t); } } //--- boolean argument boolean _test (boolean v){ //System.out.println("-- test(boolean) got " + v); return v; } @Test public void argTestBoolean() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", boolean.class); Object[] expected = { // all but Boolean throws ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, Boolean.TRUE, ILLEGAL, ILLEGAL, ILLEGAL }; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- byte argument byte _test(byte v){ //System.out.println("-- test(long) got " + v); return v; } @Test public void argTestByte() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", byte.class); Object[] expected = { // all but byte throws Byte.valueOf((byte)7), ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL }; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- short argument short _test(short v){ //System.out.println("-- test(short) got " + v); return v; } @Test public void argTestShort() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", short.class); Object[] expected = { // all but byte and short throws Short.valueOf((short)7), Short.valueOf((short)8), ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL }; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- char argument char _test(char v){ //System.out.println("-- test(char) got " + v); return v; } @Test public void argTestChar() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", char.class); Object[] expected = { // all but char throws ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, Character.valueOf('w'), ILLEGAL, ILLEGAL }; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- int argument int _test(int v){ //System.out.println("-- test(int) got " + v); return v; } @Test public void argTestInt() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", int.class); Object[] expected = { // all but byte, short, int and char throws Integer.valueOf(7), Integer.valueOf(8), Integer.valueOf(9), ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, Integer.valueOf((int)'w'), ILLEGAL, ILLEGAL }; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- long argument long _test(long v){ //System.out.println("-- test(long) got " + v); return v; } @Test public void argTestLong() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", long.class); Object[] expected = { Long.valueOf(7L),Long.valueOf(8L), Long.valueOf(9L), Long.valueOf(10L), ILLEGAL, ILLEGAL, ILLEGAL, Long.valueOf((long)'w'), ILLEGAL, ILLEGAL }; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- float argument float _test(float v){ //System.out.println("-- test(float) got " + v); return v; } @Test public void argTestFloat() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", float.class); Object[] expected = { Float.valueOf(7f), Float.valueOf(8f), Float.valueOf(9f), Float.valueOf(10f), Float.valueOf(3.1415f), ILLEGAL, ILLEGAL, Float.valueOf((float)'w'), ILLEGAL, ILLEGAL }; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- double argument double _test(double v){ //System.out.println("-- test(double) got " + v); return v; } @Test public void argTestDouble() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", double.class); Object[] expected = { Double.valueOf(7.0), Double.valueOf(8.0), Double.valueOf(9.0), Double.valueOf(10.0), Double.valueOf((double)3.1415f), Double.valueOf(3.14159), ILLEGAL, Double.valueOf((double)'w'), ILLEGAL, ILLEGAL }; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- String argument String _test(String v){ //System.out.println("-- test(String) got " + v); return v; } @Test public void argTestString() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", String.class); Object[] expected = { ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, "hello", null }; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- Object argument Object _test(Object v){ //System.out.println("-- test(String) got " + v); return v; } @Test public void argTestObject() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", Object.class); Object[] expected = testArgValues; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- Number argument Number _test(Number v){ //System.out.println("-- test(Number) got " + v); return v; } @Test public void argTestNumber() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", Number.class); Object[] expected = { Byte.valueOf((byte) 7), Short.valueOf((short) 8), Integer.valueOf(9), Long.valueOf(10), Float.valueOf(3.1415f), Double.valueOf(3.14159), ILLEGAL, ILLEGAL, ILLEGAL, null // we already used the real null to flag an IllegalArgumentException }; for (int i=0; i<testArgValues.length; i++){ invokeTest( m, testArgValues[i], expected[i]); } } } //--- array argument int[] _test(int[] v){ //System.out.println("-- test(int[]) got " + v); return v; } @Test public void argTestIntArray() throws NoSuchMethodException { if (verifyNoPropertyViolation()){ Method m = MethodTest.class.getDeclaredMethod("_test", int[].class); Object[] testVals = { new int[0], new float[0], "blah", null }; Object[] expected = { testVals[0], ILLEGAL, ILLEGAL, null }; for (int i=0; i<testVals.length; i++){ invokeTest( m, testVals[i], expected[i]); } } } //--- parameter annotation reflection @Retention(RetentionPolicy.RUNTIME) @interface A { String value(); } void noFoo() {} void noFoo(int a) {} void oneFoo (@A("arg 1")int a){} void twoFoo (int a, @A("arg 2") int b){} @Test public void testParameterAnnotations(){ if (verifyNoPropertyViolation()){ try { Method mth; Annotation[][] pai; Class<MethodTest> cls = MethodTest.class; /** mth = cls.getDeclaredMethod("noFoo"); pai = mth.getParameterAnnotations(); assertTrue("should return Annotation[0][] for noFoo()", pai != null && pai.length == 0); mth = cls.getDeclaredMethod("noFoo", int.class ); pai = mth.getParameterAnnotations(); assertTrue("should return Annotation[1][{}] for noFoo(int)", pai != null && pai.length == 1 && ((pai[0] != null) && (pai[0].length == 0))); System.out.println("noFoo(int) : " + pai[0]); **/ mth = cls.getDeclaredMethod("oneFoo", int.class); pai = mth.getParameterAnnotations(); assertTrue("should return Annotation[1][{@A}] for oneFoo(int)", pai != null && pai.length == 1 && ((pai[0] != null) && (pai[0].length == 1) && (pai[0][0] instanceof A))); System.out.println("oneFoo(@A int) : " + pai[0][0]); mth = cls.getDeclaredMethod("twoFoo", int.class, int.class); pai = mth.getParameterAnnotations(); assertTrue("should return Annotation[1][{@A}{}] for twoFoo(int,int)", pai != null && pai.length == 2 && ((pai[0] != null) && (pai[0].length == 0)) && ((pai[1] != null) && (pai[1].length == 1) && (pai[1][0] instanceof A))); System.out.println("twoFoo(int, @A int) : " + pai[0] + ',' + pai[1][0]); } catch (Throwable t){ t.printStackTrace(); fail("retrieving parameter annotation failed: " + t); } } } }