Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ValueConversionDebugger.java
41161 views
/*1* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22package nsk.share.jdi;2324import java.lang.reflect.*;25import nsk.share.*;26import nsk.share.jpda.ConversionUtils;27import com.sun.jdi.*;2829/*30* Class contains several common methods used by tests checking that values are31* correctly converted as a result of JDI interface work (e.g. when method32* 'ObjectReference.setValue(Field, Value)' is called)33*/34public class ValueConversionDebugger extends TestDebuggerType2 {3536protected static enum ValueType {37BYTE,38CHAR,39SHORT,40INT,41LONG,42FLOAT,43DOUBLE44}4546/*47* short aliases for ValueType members48*/49protected static ValueType BYTE = ValueType.BYTE;50protected static ValueType CHAR = ValueType.CHAR;51protected static ValueType SHORT = ValueType.SHORT;52protected static ValueType INT = ValueType.INT;53protected static ValueType LONG = ValueType.LONG;54protected static ValueType FLOAT = ValueType.FLOAT;55protected static ValueType DOUBLE = ValueType.DOUBLE;5657/*58* Is information lost when given PrimitiveValue converted to the59* primitive type representing by the destType60*/61public static boolean informationLoss(PrimitiveValue value, Class destType) {62/*63* Use reflection here to avoid large nested switches64* (construct method name, method is located in the nsk.share.jpda.ConversionUtils)65*/66String methodNameToCall = "informationLoss";6768Object param = null;6970if (value instanceof ByteValue) {71methodNameToCall += "ByteTo";72param = Byte.valueOf(value.byteValue());73} else if (value instanceof ShortValue) {74methodNameToCall += "ShortTo";75param = Short.valueOf(value.shortValue());76} else if (value instanceof CharValue) {77methodNameToCall += "CharTo";78param = Character.valueOf(value.charValue());79} else if (value instanceof IntegerValue) {80methodNameToCall += "IntTo";81param = Integer.valueOf(value.intValue());82} else if (value instanceof LongValue) {83methodNameToCall += "LongTo";84param = Long.valueOf(value.longValue());85} else if (value instanceof FloatValue) {86methodNameToCall += "FloatTo";87param = Float.valueOf(value.floatValue());88} else if (value instanceof DoubleValue) {89methodNameToCall += "DoubleTo";90param = Double.valueOf(value.doubleValue());91} else92throw new IllegalArgumentException("Illegal PrimitiveValue: " + value);9394if (!destType.isPrimitive())95throw new IllegalArgumentException("Illegal destType: " + destType + ", should be primitive type");9697if (destType == Byte.TYPE) {98methodNameToCall += "Byte";99} else if (destType == Short.TYPE) {100methodNameToCall += "Short";101} else if (destType == Character.TYPE) {102methodNameToCall += "Char";103} else if (destType == Integer.TYPE) {104methodNameToCall += "Int";105} else if (destType == Long.TYPE) {106methodNameToCall += "Long";107} else if (destType == Float.TYPE) {108methodNameToCall += "Float";109} else if (destType == Double.TYPE) {110methodNameToCall += "Double";111} else112throw new IllegalArgumentException("Illegal destType: " + destType + ", should be primitive type");113114java.lang.reflect.Method method;115try {116method = ConversionUtils.class.getMethod(methodNameToCall, param.getClass());117} catch (NoSuchMethodException e) {118throw new Failure("Unexpected exception: " + e, e);119}120121try {122return (Boolean)method.invoke(null, new Object[]{param});123} catch (IllegalAccessException e) {124throw new Failure("Unexpected exception: " + e, e);125} catch (InvocationTargetException e) {126throw new Failure("Unexpected exception: " + e, e);127}128}129130/*131* Is given PrimitiveValue can be converted to the primitive type represented by the132* destType without information loss133*/134public static boolean isValidConversion(PrimitiveValue value, Class destType) {135return !informationLoss(value, destType);136}137138/*139* Method is used in subclasses for creation of tested values140* (reflection is used to simplify coding)141*/142protected PrimitiveValue createValue(Object arr, int arrayIndex) {143PrimitiveValue value;144145if (arr instanceof byte[]) {146value = debuggee.VM().mirrorOf(Array.getByte(arr,arrayIndex));147} else if (arr instanceof char[]) {148value = debuggee.VM().mirrorOf(Array.getChar(arr,arrayIndex));149} else if (arr instanceof double[]) {150value = debuggee.VM().mirrorOf(Array.getDouble(arr,arrayIndex));151} else if (arr instanceof float[]) {152value = debuggee.VM().mirrorOf(Array.getFloat(arr,arrayIndex));153} else if (arr instanceof int[]) {154value = debuggee.VM().mirrorOf(Array.getInt(arr,arrayIndex));155} else if (arr instanceof long[]) {156value = debuggee.VM().mirrorOf(Array.getLong(arr,arrayIndex));157} else if (arr instanceof short[]) {158value = debuggee.VM().mirrorOf(Array.getShort(arr,arrayIndex));159} else {160setSuccess(false);161throw new TestBug("Unexpected object was passed in the 'createValue': " + arr);162}163164return value;165}166167/*168* used by subclasses for debug output169* (modified in the method 'isValidConversion')170*/171protected String lastConversion;172173/*174* Is given PrimitiveValue can be converted to the primitive type represented by the given type175* without information loss176*/177protected boolean isValidConversion(ValueType type, PrimitiveValue value) {178com.sun.jdi.Type fromType = value.type();179180boolean ret = false;181lastConversion = " conversion from "182+ value + "(" + fromType + ")" + " to ";183switch (type) {184case BYTE:185byte b = value.byteValue();186ret = isValidConversion(value, Byte.TYPE);187lastConversion += b + "(byte)";188break;189case CHAR:190char c = value.charValue();191ret = isValidConversion(value, Character.TYPE);192lastConversion += Integer.toHexString(c) + "(char)";193break;194case DOUBLE:195double d = value.doubleValue();196ret = isValidConversion(value, Double.TYPE);197lastConversion += d + "(double)";198break;199case FLOAT:200float f = value.floatValue();201ret = isValidConversion(value, Float.TYPE);202lastConversion += f + "(float)";203break;204case INT:205int i = value.intValue();206ret = isValidConversion(value, Integer.TYPE);207lastConversion += i + "(int)";208break;209case LONG:210long j = value.longValue();211ret = isValidConversion(value, Long.TYPE);212lastConversion += j + "(long)";213break;214case SHORT:215short s = value.shortValue();216ret = isValidConversion(value, Short.TYPE);217lastConversion += s + "(short)";218break;219default:220throw new IllegalArgumentException("Invalid type: " + type);221}222return ret;223}224225/*226* Used in subclasses to check that given PrimitiveValue was correctly converted as a result227* of JDI interface work (retValue - conversion result)228* (229* example:230* test assigns DoubleValue = 1.5 (value) to the byte Field (retValue - ByteValue = 1),231* in this case we should check that value.byteValue() == retValue.byteValue()232* )233*/234protected void checkValueConversion(PrimitiveValue value, PrimitiveValue retValue) {235boolean res;236237if (retValue instanceof ByteValue) {238res = value.byteValue() != retValue.byteValue();239} else if (retValue instanceof ShortValue) {240res = value.shortValue() != retValue.shortValue();241} else if (retValue instanceof CharValue) {242res = value.charValue() != retValue.charValue();243} else if (retValue instanceof IntegerValue) {244res = value.intValue() != retValue.intValue();245} else if (retValue instanceof LongValue) {246res = value.longValue() != retValue.longValue();247} else if (retValue instanceof FloatValue) {248res = value.floatValue() != retValue.floatValue();249} else if (retValue instanceof DoubleValue) {250res = value.doubleValue() != retValue.doubleValue();251} else {252throw new TestBug("Invalid value type in the 'checkValueConversion': " + retValue.type().name());253}254255if (res) {256setSuccess(false);257complain("Conversion error");258complain("From type: " + value.type().name() + ", to type: " + retValue.type().name());259complain(retValue + " != " + value);260display("");261}262}263}264265266