//
// 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);
}
}
}
}