blob: 8e15c688b4149f8e67fad0d1b75d9a94c6f0cf36 [file] [log] [blame]
/*
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package nsk.share.jdi;
import java.lang.reflect.*;
import nsk.share.*;
import nsk.share.jpda.ConversionUtils;
import com.sun.jdi.*;
/*
* Class contains several common methods used by tests checking that values are
* correctly converted as a result of JDI interface work (e.g. when method
* 'ObjectReference.setValue(Field, Value)' is called)
*/
public class ValueConversionDebugger extends TestDebuggerType2 {
protected static enum ValueType {
BYTE,
CHAR,
SHORT,
INT,
LONG,
FLOAT,
DOUBLE
}
/*
* short aliases for ValueType members
*/
protected static ValueType BYTE = ValueType.BYTE;
protected static ValueType CHAR = ValueType.CHAR;
protected static ValueType SHORT = ValueType.SHORT;
protected static ValueType INT = ValueType.INT;
protected static ValueType LONG = ValueType.LONG;
protected static ValueType FLOAT = ValueType.FLOAT;
protected static ValueType DOUBLE = ValueType.DOUBLE;
/*
* Is information lost when given PrimitiveValue converted to the
* primitive type representing by the destType
*/
public static boolean informationLoss(PrimitiveValue value, Class destType) {
/*
* Use reflection here to avoid large nested switches
* (construct method name, method is located in the nsk.share.jpda.ConversionUtils)
*/
String methodNameToCall = "informationLoss";
Object param = null;
if (value instanceof ByteValue) {
methodNameToCall += "ByteTo";
param = new Byte(value.byteValue());
} else if (value instanceof ShortValue) {
methodNameToCall += "ShortTo";
param = new Short(value.shortValue());
} else if (value instanceof CharValue) {
methodNameToCall += "CharTo";
param = new Character(value.charValue());
} else if (value instanceof IntegerValue) {
methodNameToCall += "IntTo";
param = new Integer(value.intValue());
} else if (value instanceof LongValue) {
methodNameToCall += "LongTo";
param = new Long(value.longValue());
} else if (value instanceof FloatValue) {
methodNameToCall += "FloatTo";
param = new Float(value.floatValue());
} else if (value instanceof DoubleValue) {
methodNameToCall += "DoubleTo";
param = new Double(value.doubleValue());
} else
throw new IllegalArgumentException("Illegal PrimitiveValue: " + value);
if (!destType.isPrimitive())
throw new IllegalArgumentException("Illegal destType: " + destType + ", should be primitive type");
if (destType == Byte.TYPE) {
methodNameToCall += "Byte";
} else if (destType == Short.TYPE) {
methodNameToCall += "Short";
} else if (destType == Character.TYPE) {
methodNameToCall += "Char";
} else if (destType == Integer.TYPE) {
methodNameToCall += "Int";
} else if (destType == Long.TYPE) {
methodNameToCall += "Long";
} else if (destType == Float.TYPE) {
methodNameToCall += "Float";
} else if (destType == Double.TYPE) {
methodNameToCall += "Double";
} else
throw new IllegalArgumentException("Illegal destType: " + destType + ", should be primitive type");
java.lang.reflect.Method method;
try {
method = ConversionUtils.class.getMethod(methodNameToCall, param.getClass());
} catch (NoSuchMethodException e) {
throw new Failure("Unexpected exception: " + e, e);
}
try {
return (Boolean)method.invoke(null, new Object[]{param});
} catch (IllegalAccessException e) {
throw new Failure("Unexpected exception: " + e, e);
} catch (InvocationTargetException e) {
throw new Failure("Unexpected exception: " + e, e);
}
}
/*
* Is given PrimitiveValue can be converted to the primitive type represented by the
* destType without information loss
*/
public static boolean isValidConversion(PrimitiveValue value, Class destType) {
return !informationLoss(value, destType);
}
/*
* Method is used in subclasses for creation of tested values
* (reflection is used to simplify coding)
*/
protected PrimitiveValue createValue(Object arr, int arrayIndex) {
PrimitiveValue value;
if (arr instanceof byte[]) {
value = debuggee.VM().mirrorOf(Array.getByte(arr,arrayIndex));
} else if (arr instanceof char[]) {
value = debuggee.VM().mirrorOf(Array.getChar(arr,arrayIndex));
} else if (arr instanceof double[]) {
value = debuggee.VM().mirrorOf(Array.getDouble(arr,arrayIndex));
} else if (arr instanceof float[]) {
value = debuggee.VM().mirrorOf(Array.getFloat(arr,arrayIndex));
} else if (arr instanceof int[]) {
value = debuggee.VM().mirrorOf(Array.getInt(arr,arrayIndex));
} else if (arr instanceof long[]) {
value = debuggee.VM().mirrorOf(Array.getLong(arr,arrayIndex));
} else if (arr instanceof short[]) {
value = debuggee.VM().mirrorOf(Array.getShort(arr,arrayIndex));
} else {
setSuccess(false);
throw new TestBug("Unexpected object was passed in the 'createValue': " + arr);
}
return value;
}
/*
* used by subclasses for debug output
* (modified in the method 'isValidConversion')
*/
protected String lastConversion;
/*
* Is given PrimitiveValue can be converted to the primitive type represented by the given type
* without information loss
*/
protected boolean isValidConversion(ValueType type, PrimitiveValue value) {
com.sun.jdi.Type fromType = value.type();
boolean ret = false;
lastConversion = " conversion from "
+ value + "(" + fromType + ")" + " to ";
switch (type) {
case BYTE:
byte b = value.byteValue();
ret = isValidConversion(value, Byte.TYPE);
lastConversion += b + "(byte)";
break;
case CHAR:
char c = value.charValue();
ret = isValidConversion(value, Character.TYPE);
lastConversion += Integer.toHexString(c) + "(char)";
break;
case DOUBLE:
double d = value.doubleValue();
ret = isValidConversion(value, Double.TYPE);
lastConversion += d + "(double)";
break;
case FLOAT:
float f = value.floatValue();
ret = isValidConversion(value, Float.TYPE);
lastConversion += f + "(float)";
break;
case INT:
int i = value.intValue();
ret = isValidConversion(value, Integer.TYPE);
lastConversion += i + "(int)";
break;
case LONG:
long j = value.longValue();
ret = isValidConversion(value, Long.TYPE);
lastConversion += j + "(long)";
break;
case SHORT:
short s = value.shortValue();
ret = isValidConversion(value, Short.TYPE);
lastConversion += s + "(short)";
break;
default:
throw new IllegalArgumentException("Invalid type: " + type);
}
return ret;
}
/*
* Used in subclasses to check that given PrimitiveValue was correctly converted as a result
* of JDI interface work (retValue - conversion result)
* (
* example:
* test assigns DoubleValue = 1.5 (value) to the byte Field (retValue - ByteValue = 1),
* in this case we should check that value.byteValue() == retValue.byteValue()
* )
*/
protected void checkValueConversion(PrimitiveValue value, PrimitiveValue retValue) {
boolean res;
if (retValue instanceof ByteValue) {
res = value.byteValue() != retValue.byteValue();
} else if (retValue instanceof ShortValue) {
res = value.shortValue() != retValue.shortValue();
} else if (retValue instanceof CharValue) {
res = value.charValue() != retValue.charValue();
} else if (retValue instanceof IntegerValue) {
res = value.intValue() != retValue.intValue();
} else if (retValue instanceof LongValue) {
res = value.longValue() != retValue.longValue();
} else if (retValue instanceof FloatValue) {
res = value.floatValue() != retValue.floatValue();
} else if (retValue instanceof DoubleValue) {
res = value.doubleValue() != retValue.doubleValue();
} else {
throw new TestBug("Invalid value type in the 'checkValueConversion': " + retValue.type().name());
}
if (res) {
setSuccess(false);
complain("Conversion error");
complain("From type: " + value.type().name() + ", to type: " + retValue.type().name());
complain(retValue + " != " + value);
display("");
}
}
}